# HG changeset patch # User John W. Eaton # Date 1468271133 14400 # Node ID 0f6fc2ec3b1ab690c755b89a85608706a2cca835 # Parent 66db9a493c84b0f86d56739ad48f4c9f4d9078ef move call_stack class to a separate file * call-stack.h, call-stack.cc: New files. Move call_stack class here from toplev.h and toplev.cc. Update include file lists in other files as needed. * libinterp/corefcn/module.mk: Update. diff -r 66db9a493c84 -r 0f6fc2ec3b1a libinterp/corefcn/call-stack.cc --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/libinterp/corefcn/call-stack.cc Mon Jul 11 17:05:33 2016 -0400 @@ -0,0 +1,583 @@ +/* + +Copyright (C) 1995-2015 John W. Eaton + +This file is part of Octave. + +Octave is free software; you can redistribute it and/or modify it +under the terms of the GNU General Public License as published by the +Free Software Foundation; either version 3 of the License, or (at your +option) any later version. + +Octave is distributed in the hope that it will be useful, but WITHOUT +ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or +FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License +for more details. + +You should have received a copy of the GNU General Public License +along with Octave; see the file COPYING. If not, see +. + +*/ + +#if defined (HAVE_CONFIG_H) +# include "config.h" +#endif + +#include "singleton-cleanup.h" + +#include "call-stack.h" +#include "oct-map.h" +#include "ov.h" +#include "ov-fcn.h" +#include "ov-usr-fcn.h" + +octave_call_stack *octave_call_stack::instance = 0; + +std::string +octave_call_stack::stack_frame::fcn_file_name (void) const +{ + return m_fcn ? m_fcn->fcn_file_name () : ""; +} + +std::string +octave_call_stack::stack_frame::fcn_name (bool print_subfn) const +{ + std::string retval; + + if (m_fcn) + { + std::string parent_fcn_name = m_fcn->parent_fcn_name (); + + if (print_subfn && ! parent_fcn_name.empty ()) + retval = parent_fcn_name + Vfilemarker; + + retval += m_fcn->name (); + } + else + retval = ""; + + return retval; +} + +bool +octave_call_stack::stack_frame::operator== (const octave_call_stack::stack_frame &rhs) const +{ + if (this->line () != rhs.line ()) + return false; + else if (this->column () != rhs.column ()) + return false; + else if (this->fcn_file_name () != rhs.fcn_file_name ()) + return false; + else if (this->fcn_name () != rhs.fcn_name ()) + return false; + else + return true; +} + +void +octave_call_stack::create_instance (void) +{ + instance = new octave_call_stack (); + + if (instance) + { + instance->do_push (0, symbol_table::top_scope (), 0); + + singleton_cleanup_list::add (cleanup_instance); + } +} + +int +octave_call_stack::do_current_line (void) const +{ + int retval = -1; + + if (! cs.empty ()) + { + const stack_frame& elt = cs[curr_frame]; + retval = elt.m_line; + } + + return retval; +} + +int +octave_call_stack::do_current_column (void) const +{ + int retval = -1; + + if (! cs.empty ()) + { + const stack_frame& elt = cs[curr_frame]; + retval = elt.m_column; + } + + return retval; +} + +size_t +octave_call_stack::do_num_user_code_frames + (octave_idx_type& curr_user_frame) const +{ + size_t retval = 0; + + curr_user_frame = 0; + + // Look for the caller of dbstack. + size_t xframe = cs[curr_frame].m_prev; + + bool found = false; + + size_t k = cs.size (); + + for (const_reverse_iterator p = cs.rbegin (); p != cs.rend (); p++) + { + octave_function *f = (*p).m_fcn; + + if (--k == xframe) + found = true; + + if (f && f->is_user_code ()) + { + if (! found) + curr_user_frame++; + + retval++; + } + } + + // We counted how many user frames were not the one, in reverse. + // Now set curr_user_frame to be the index in the other direction. + curr_user_frame = retval - curr_user_frame - 1; + + return retval; +} + +octave_user_code * +octave_call_stack::do_caller_user_code (size_t nskip) const +{ + octave_user_code *retval = 0; + + const_iterator p = cs.end (); + + while (p != cs.begin ()) + { + const stack_frame& elt = *(--p); + + octave_function *f = elt.m_fcn; + + if (f && f->is_user_code ()) + { + if (nskip > 0) + nskip--; + else + { + retval = dynamic_cast (f); + break; + } + } + } + + return retval; +} + +int +octave_call_stack::do_caller_user_code_line (void) const +{ + int retval = -1; + + const_iterator p = cs.end (); + + while (p != cs.begin ()) + { + const stack_frame& elt = *(--p); + + octave_function *f = elt.m_fcn; + + if (f && f->is_user_code ()) + { + if (elt.m_line > 0) + { + retval = elt.m_line; + break; + } + } + } + + return retval; +} + +int +octave_call_stack::do_caller_user_code_column (void) const +{ + int retval = -1; + + const_iterator p = cs.end (); + + while (p != cs.begin ()) + { + const stack_frame& elt = *(--p); + + octave_function *f = elt.m_fcn; + + if (f && f->is_user_code ()) + { + if (elt.m_column) + { + retval = elt.m_column; + break; + } + } + } + + return retval; +} + +octave_user_code * +octave_call_stack::do_debug_user_code (void) const +{ + octave_user_code *retval = 0; + + // This should never happen... + if (curr_frame == 0) + return retval; + + // Start looking with the caller of the calling debug function. + size_t i = cs[curr_frame].m_prev; + + while (i != 0) + { + const stack_frame& elt = cs[i--]; + + octave_function *f = elt.m_fcn; + + if (f && f->is_user_code ()) + { + retval = dynamic_cast (f); + break; + } + } + + return retval; +} + +int +octave_call_stack::do_debug_user_code_line (void) const +{ + int retval = -1; + + // This should never happen... + if (curr_frame == 0) + return retval; + + // Start looking with the caller of the calling debug function. + size_t i = cs[curr_frame].m_prev; + + while (i != 0) + { + const stack_frame& elt = cs[i--]; + + octave_function *f = elt.m_fcn; + + if (f && f->is_user_code ()) + { + if (elt.m_line) + { + retval = elt.m_line; + break; + } + } + } + + return retval; +} + +int +octave_call_stack::do_debug_user_code_column (void) const +{ + int retval = -1; + + // This should never happen... + if (curr_frame == 0) + return retval; + + // Start looking with the caller of the calling debug function. + size_t i = cs[curr_frame].m_prev; + + while (i != 0) + { + const stack_frame& elt = cs[i--]; + + octave_function *f = elt.m_fcn; + + if (f && f->is_user_code ()) + { + if (elt.m_column) + { + retval = elt.m_column; + break; + } + } + } + + return retval; +} + +bool +octave_call_stack::do_all_scripts (void) const +{ + bool retval = true; + + const_iterator p = cs.end (); + + while (p != cs.begin ()) + { + const stack_frame& elt = *(--p); + + octave_function *f = elt.m_fcn; + + if (f && ! f->is_user_script ()) + { + retval = false; + break; + } + } + + return retval; +} + +// Use static fields for the best efficiency. +// NOTE: C++0x will allow these two to be merged into one. +static const char *bt_fieldnames[] = { "file", "name", "line", + "column", "scope", "context", 0 + }; +static const octave_fields bt_fields (bt_fieldnames); + +octave_map +octave_call_stack::empty_backtrace (void) +{ + return octave_map (dim_vector (0, 1), bt_fields); +} + +std::list +octave_call_stack::do_backtrace_frames (size_t nskip, + octave_idx_type& curr_user_frame) const +{ + std::list retval; + + size_t user_code_frames = do_num_user_code_frames (curr_user_frame); + + size_t nframes = nskip <= user_code_frames ? user_code_frames - nskip : 0; + + // Our list is reversed. + curr_user_frame = nframes - curr_user_frame - 1; + + if (nframes > 0) + { + for (const_reverse_iterator p = cs.rbegin (); p != cs.rend (); p++) + { + const stack_frame& elt = *p; + + octave_function *f = elt.m_fcn; + + if (f && f->is_user_code ()) + { + if (nskip > 0) + nskip--; + else + retval.push_back (elt); + } + } + } + + return retval; +} + +octave_map +octave_call_stack::do_backtrace (size_t nskip, + octave_idx_type& curr_user_frame, + bool print_subfn) const +{ + std::list frames + = do_backtrace_frames (nskip, curr_user_frame); + + size_t nframes = frames.size (); + + octave_map retval (dim_vector (nframes, 1), bt_fields); + + Cell& file = retval.contents (0); + Cell& name = retval.contents (1); + Cell& line = retval.contents (2); + Cell& column = retval.contents (3); + Cell& scope = retval.contents (4); + Cell& context = retval.contents (5); + + octave_idx_type k = 0; + + for (std::list::const_iterator p = frames.begin (); + p != frames.end (); p++) + { + const stack_frame& elt = *p; + + scope(k) = elt.m_scope; + context(k) = elt.m_context; + file(k) = elt.fcn_file_name (); + name(k) = elt.fcn_name (print_subfn); + line(k) = elt.m_line; + column(k) = elt.m_column; + + k++; + } + + return retval; +} + +bool +octave_call_stack::do_goto_frame (size_t n, bool verbose) +{ + bool retval = false; + + if (n < cs.size ()) + { + retval = true; + + curr_frame = n; + + const stack_frame& elt = cs[n]; + + symbol_table::set_scope_and_context (elt.m_scope, elt.m_context); + + if (verbose) + octave_stdout << "stopped in " << elt.fcn_name () + << " at line " << elt.m_line + << " column " << elt.m_column + << " [" << elt.fcn_file_name () << "] " + << " (scope = " << elt.m_scope + << "[context = " << elt.m_context << "])" + << std::endl; + } + + return retval; +} + +bool +octave_call_stack::do_goto_frame_relative (int nskip, bool verbose) +{ + bool retval = false; + + int incr = 0; + + if (nskip < 0) + incr = -1; + else if (nskip > 0) + incr = 1; + + // Start looking with the caller of dbup/dbdown/keyboard. + size_t xframe = cs[curr_frame].m_prev; + + while (true) + { + if ((incr < 0 && xframe == 0) || (incr > 0 && xframe == cs.size () - 1)) + break; + + xframe += incr; + + const stack_frame& elt = cs[xframe]; + + octave_function *f = elt.m_fcn; + + if (xframe == 0 || (f && f->is_user_code ())) + { + if (nskip > 0) + nskip--; + else if (nskip < 0) + nskip++; + + if (nskip == 0) + { + curr_frame = xframe; + cs[cs.size () - 1].m_prev = curr_frame; + + symbol_table::set_scope_and_context (elt.m_scope, elt.m_context); + + if (verbose) + { + std::ostringstream buf; + + if (f) + buf << "stopped in " << elt.fcn_name () + << " at line " << elt.m_line + << " [" << elt.fcn_file_name () << "] " + << std::endl; + else + buf << "at top level" << std::endl; + + octave_stdout << buf.str (); + } + + retval = true; + break; + } + } + else if (incr == 0) // Break out of infinite loop by choosing an incr. + incr = -1; + + // There is no need to set scope and context here. That will + // happen when the dbup/dbdown/keyboard frame is popped and we + // jump to the new "prev" frame set above. + } + + return retval; +} + +void +octave_call_stack::do_goto_caller_frame (void) +{ + size_t xframe = curr_frame; + + bool skipped = false; + + while (xframe != 0) + { + xframe = cs[xframe].m_prev; + + const stack_frame& elt = cs[xframe]; + + octave_function *f = elt.m_fcn; + + if (elt.m_scope == cs[0].m_scope || (f && f->is_user_code ())) + { + if (! skipped) + // We found the current user code frame, so skip it. + skipped = true; + else + { + // We found the caller user code frame. + stack_frame tmp (elt); + tmp.m_prev = curr_frame; + + curr_frame = cs.size (); + + cs.push_back (tmp); + + symbol_table::set_scope_and_context (tmp.m_scope, tmp.m_context); + + break; + } + } + } +} + +void +octave_call_stack::do_goto_base_frame (void) +{ + stack_frame tmp (cs[0]); + tmp.m_prev = curr_frame; + + curr_frame = cs.size (); + + cs.push_back (tmp); + + symbol_table::set_scope_and_context (tmp.m_scope, tmp.m_context); +} diff -r 66db9a493c84 -r 0f6fc2ec3b1a libinterp/corefcn/call-stack.h --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/libinterp/corefcn/call-stack.h Mon Jul 11 17:05:33 2016 -0400 @@ -0,0 +1,478 @@ +/* + +Copyright (C) 1993-2015 John W. Eaton + +This file is part of Octave. + +Octave is free software; you can redistribute it and/or modify it +under the terms of the GNU General Public License as published by the +Free Software Foundation; either version 3 of the License, or (at your +option) any later version. + +Octave is distributed in the hope that it will be useful, but WITHOUT +ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or +FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License +for more details. + +You should have received a copy of the GNU General Public License +along with Octave; see the file COPYING. If not, see +. + +*/ + +#if ! defined (octave_call_stack_h) +#define octave_call_stack_h 1 + +#include "octave-config.h" + +#include +#include + +class octave_function; +class octave_user_code; +class octave_user_script; + +#include "input.h" +#include "oct-map.h" +#include "symtab.h" + +class +OCTINTERP_API +octave_call_stack +{ +protected: + + octave_call_stack (void) : cs (), curr_frame (0) { } + +public: + + class stack_frame + { + public: + + friend class octave_call_stack; + + stack_frame (octave_function *fcn = 0, symbol_table::scope_id scope = 0, + symbol_table::context_id context = 0, size_t prev = 0) + : m_fcn (fcn), m_line (-1), m_column (-1), m_scope (scope), + m_context (context), m_prev (prev) + { } + + stack_frame (const stack_frame& elt) + : m_fcn (elt.m_fcn), m_line (elt.m_line), m_column (elt.m_column), + m_scope (elt.m_scope), m_context (elt.m_context), m_prev (elt.m_prev) + { } + + int line (void) const { return m_line; } + + int column (void) const { return m_column; } + + std::string fcn_file_name (void) const; + + std::string fcn_name (bool print_subfn = true) const; + + bool operator== (const stack_frame &rhs) const; + + private: + + octave_function *m_fcn; + int m_line; + int m_column; + symbol_table::scope_id m_scope; + symbol_table::context_id m_context; + size_t m_prev; + }; + + typedef std::deque::iterator iterator; + typedef std::deque::const_iterator const_iterator; + + typedef std::deque::reverse_iterator reverse_iterator; + typedef std::deque::const_reverse_iterator const_reverse_iterator; + + static void create_instance (void); + + static bool instance_ok (void) + { + bool retval = true; + + if (! instance) + create_instance (); + + if (! instance) + error ("unable to create call stack object!"); + + return retval; + } + + // Current function (top of stack). + static octave_function *current (void) + { + return instance_ok () ? instance->do_current () : 0; + } + + // Current line in current function. + static int current_line (void) + { + return instance_ok () ? instance->do_current_line () : -1; + } + + // Current column in current function. + static int current_column (void) + { + return instance_ok () ? instance->do_current_column () : -1; + } + + // Caller function, may be built-in. + static octave_function *caller (void) + { + return instance_ok () ? instance->do_caller () : 0; + } + + static size_t current_frame (void) + { + return instance_ok () ? instance->do_current_frame () : 0; + } + + static size_t size (void) + { + return instance_ok () ? instance->do_size () : 0; + } + + static size_t num_user_code_frames (octave_idx_type& curr_user_frame) + { + return instance_ok () + ? instance->do_num_user_code_frames (curr_user_frame) : 0; + } + + static symbol_table::scope_id current_scope (void) + { + return instance_ok () ? instance->do_current_scope () : 0; + } + + static symbol_table::context_id current_context (void) + { + return instance_ok () ? instance->do_current_context () : 0; + } + +#if 0 + static stack_frame frame (size_t idx) + { + return instance_ok () ? instance->do_frame (idx) : stack_frame (); + } +#endif + + // Function at location N on the call stack (N == 0 is current), may + // be built-in. + static octave_function *element (size_t n) + { + return instance_ok () ? instance->do_element (n) : 0; + } + + // User code caller. + static octave_user_code *caller_user_code (size_t nskip = 0) + { + return instance_ok () ? instance->do_caller_user_code (nskip) : 0; + } + + // Line in user code caller. + static int caller_user_code_line (void) + { + return instance_ok () ? instance->do_caller_user_code_line () : -1; + } + + // Column in user code caller. + static int caller_user_code_column (void) + { + return instance_ok () ? instance->do_caller_user_code_column () : -1; + } + + // Current function that we are debugging. + static octave_user_code *debug_user_code (void) + { + return instance_ok () ? instance->do_debug_user_code () : 0; + } + + // Line number in current function that we are debugging. + static int debug_user_code_line (void) + { + return instance_ok () ? instance->do_debug_user_code_line () : 0; + } + + // Column number in current function that we are debugging. + static int debug_user_code_column (void) + { + return instance_ok () ? instance->do_debug_user_code_column () : 0; + } + + // Return TRUE if all elements on the call stack are scripts. + static bool all_scripts (void) + { + return instance_ok () ? instance->do_all_scripts () : false; + } + + static void + push (octave_function *f, + symbol_table::scope_id scope = symbol_table::current_scope (), + symbol_table::context_id context = symbol_table::current_context ()) + { + if (instance_ok ()) + instance->do_push (f, scope, context); + } + + static void + push (symbol_table::scope_id scope = symbol_table::current_scope (), + symbol_table::context_id context = symbol_table::current_context ()) + { + if (instance_ok ()) + instance->do_push (0, scope, context); + } + + static void set_location (int l, int c) + { + if (instance_ok ()) + instance->do_set_location (l, c); + } + + static void set_line (int l) + { + if (instance_ok ()) + instance->do_set_line (l); + } + + static void set_column (int c) + { + if (instance_ok ()) + instance->do_set_column (c); + } + + static bool goto_frame (size_t n = 0, bool verbose = false) + { + return instance_ok () ? instance->do_goto_frame (n, verbose) : false; + } + + static void restore_frame (size_t n) + { + goto_frame (n); + } + + static bool goto_frame_relative (int n, bool verbose = false) + { + return instance_ok () + ? instance->do_goto_frame_relative (n, verbose) : false; + } + + static void goto_caller_frame (void) + { + if (instance_ok ()) + instance->do_goto_caller_frame (); + } + + static void goto_base_frame (void) + { + if (instance_ok ()) + instance->do_goto_base_frame (); + } + + static octave_map backtrace (size_t nskip = 0) + { + octave_idx_type curr_user_frame = -1; + + return instance_ok () + ? instance->do_backtrace (nskip, curr_user_frame, true) + : octave_map (); + } + + static octave_map backtrace (size_t nskip, octave_idx_type& curr_user_frame, + bool print_subfn = true) + { + return instance_ok () + ? instance->do_backtrace (nskip, curr_user_frame, print_subfn) + : octave_map (); + } + + static std::list + backtrace_frames (size_t nskip = 0) + { + octave_idx_type curr_user_frame = -1; + + return instance_ok () + ? instance->do_backtrace_frames (nskip, curr_user_frame) + : std::list (); + } + + static std::list + backtrace_frames (size_t nskip, octave_idx_type& curr_user_frame) + { + return instance_ok () + ? instance->do_backtrace_frames (nskip, curr_user_frame) + : std::list (); + } + + static octave_map empty_backtrace (void); + + static void pop (void) + { + if (instance_ok ()) + instance->do_pop (); + } + + static void clear (void) + { + if (instance_ok ()) + instance->do_clear (); + } + +private: + + // The current call stack. + std::deque cs; + + size_t curr_frame; + + static octave_call_stack *instance; + + static void cleanup_instance (void) { delete instance; instance = 0; } + + int do_current_line (void) const; + + int do_current_column (void) const; + + octave_function *do_caller (void) const + { + return curr_frame > 1 ? cs[curr_frame-1].m_fcn : cs[0].m_fcn; + } + + size_t do_current_frame (void) { return curr_frame; } + + size_t do_size (void) { return cs.size (); } + + size_t do_num_user_code_frames (octave_idx_type& curr_user_frame) const; + + symbol_table::scope_id do_current_scope (void) const + { + return curr_frame > 0 && curr_frame < cs.size () + ? cs[curr_frame].m_scope : 0; + } + + symbol_table::context_id do_current_context (void) const + { + return curr_frame > 0 && curr_frame < cs.size () + ? cs[curr_frame].m_context : 0; + } + +#if 0 + const stack_frame& do_frame (size_t idx) + { + static stack_frame foobar; + + return idx < cs.size () ? cs[idx] : foobar; + } +#endif + + octave_function *do_element (size_t n) + { + octave_function *retval = 0; + + if (cs.size () > n) + { + stack_frame& elt = cs[n]; + retval = elt.m_fcn; + } + + return retval; + } + + octave_user_code *do_caller_user_code (size_t nskip) const; + int do_caller_user_code_line (void) const; + int do_caller_user_code_column (void) const; + + octave_user_code *do_debug_user_code (void) const; + int do_debug_user_code_line (void) const; + int do_debug_user_code_column (void) const; + + bool do_all_scripts (void) const; + + void do_push (octave_function *fcn, symbol_table::scope_id scope, + symbol_table::context_id context) + { + size_t prev_frame = curr_frame; + curr_frame = cs.size (); + cs.push_back (stack_frame (fcn, scope, context, prev_frame)); + symbol_table::set_scope_and_context (scope, context); + } + + octave_function *do_current (void) const + { + octave_function *retval = 0; + + if (! cs.empty ()) + { + const stack_frame& elt = cs[curr_frame]; + retval = elt.m_fcn; + } + + return retval; + } + + void do_set_location (int l, int c) + { + if (! cs.empty ()) + { + stack_frame& elt = cs.back (); + + elt.m_line = l; + elt.m_column = c; + } + } + + void do_set_line (int l) + { + if (! cs.empty ()) + { + stack_frame& elt = cs.back (); + + elt.m_line = l; + } + } + + void do_set_column (int c) + { + if (! cs.empty ()) + { + stack_frame& elt = cs.back (); + + elt.m_column = c; + } + } + + std::list + do_backtrace_frames (size_t nskip, octave_idx_type& curr_user_frame) const; + + octave_map do_backtrace (size_t nskip, + octave_idx_type& curr_user_frame, + bool print_subfn) const; + + bool do_goto_frame (size_t n, bool verbose); + + bool do_goto_frame_relative (int n, bool verbose); + + void do_goto_caller_frame (void); + + void do_goto_base_frame (void); + + void do_pop (void) + { + if (cs.size () > 1) + { + const stack_frame& elt = cs.back (); + curr_frame = elt.m_prev; + cs.pop_back (); + const stack_frame& new_elt = cs[curr_frame]; + symbol_table::set_scope_and_context (new_elt.m_scope, new_elt.m_context); + } + } + + void do_clear (void) { cs.clear (); } +}; + +#endif diff -r 66db9a493c84 -r 0f6fc2ec3b1a libinterp/corefcn/debug.cc --- a/libinterp/corefcn/debug.cc Mon Jul 11 16:34:02 2016 -0400 +++ b/libinterp/corefcn/debug.cc Mon Jul 11 17:05:33 2016 -0400 @@ -35,6 +35,7 @@ #include "file-stat.h" #include "singleton-cleanup.h" +#include "call-stack.h" #include "defun.h" #include "error.h" #include "file-ops.h" diff -r 66db9a493c84 -r 0f6fc2ec3b1a libinterp/corefcn/defun.cc --- a/libinterp/corefcn/defun.cc Mon Jul 11 16:34:02 2016 -0400 +++ b/libinterp/corefcn/defun.cc Mon Jul 11 17:05:33 2016 -0400 @@ -28,6 +28,7 @@ #include #include +#include "call-stack.h" #include "defun.h" #include "dynamic-ld.h" #include "error.h" diff -r 66db9a493c84 -r 0f6fc2ec3b1a libinterp/corefcn/error.cc --- a/libinterp/corefcn/error.cc Mon Jul 11 16:34:02 2016 -0400 +++ b/libinterp/corefcn/error.cc Mon Jul 11 17:05:33 2016 -0400 @@ -32,6 +32,7 @@ #include #include +#include "call-stack.h" #include "debug.h" #include "defun.h" #include "error.h" diff -r 66db9a493c84 -r 0f6fc2ec3b1a libinterp/corefcn/help.cc --- a/libinterp/corefcn/help.cc Mon Jul 11 16:34:02 2016 -0400 +++ b/libinterp/corefcn/help.cc Mon Jul 11 17:05:33 2016 -0400 @@ -40,6 +40,7 @@ #include "oct-locbuf.h" #include "str-vec.h" +#include "call-stack.h" #include #include "Cell.h" #include "defun.h" diff -r 66db9a493c84 -r 0f6fc2ec3b1a libinterp/corefcn/input.cc --- a/libinterp/corefcn/input.cc Mon Jul 11 16:34:02 2016 -0400 +++ b/libinterp/corefcn/input.cc Mon Jul 11 17:05:33 2016 -0400 @@ -40,6 +40,7 @@ #include "quit.h" #include "str-vec.h" +#include "call-stack.h" #include "debug.h" #include "defun.h" #include "dirfns.h" diff -r 66db9a493c84 -r 0f6fc2ec3b1a libinterp/corefcn/ls-mat5.cc --- a/libinterp/corefcn/ls-mat5.cc Mon Jul 11 16:34:02 2016 -0400 +++ b/libinterp/corefcn/ls-mat5.cc Mon Jul 11 17:05:33 2016 -0400 @@ -51,6 +51,7 @@ #include "oct-locbuf.h" #include "Cell.h" +#include "call-stack.h" #include "defun.h" #include "error.h" #include "errwarn.h" diff -r 66db9a493c84 -r 0f6fc2ec3b1a libinterp/corefcn/mex.cc --- a/libinterp/corefcn/mex.cc Mon Jul 11 16:34:02 2016 -0400 +++ b/libinterp/corefcn/mex.cc Mon Jul 11 17:05:33 2016 -0400 @@ -38,6 +38,7 @@ #include "oct-locbuf.h" #include "Cell.h" +#include "call-stack.h" #include "error.h" // mxArray must be declared as a class before including mexproto.h. #include "mxarray.h" diff -r 66db9a493c84 -r 0f6fc2ec3b1a libinterp/corefcn/module.mk --- a/libinterp/corefcn/module.mk Mon Jul 11 16:34:02 2016 -0400 +++ b/libinterp/corefcn/module.mk Mon Jul 11 17:05:33 2016 -0400 @@ -26,6 +26,7 @@ libinterp/corefcn/base-text-renderer.h \ libinterp/corefcn/Cell.h \ libinterp/corefcn/c-file-ptr-stream.h \ + libinterp/corefcn/call-stack.h \ libinterp/corefcn/cdisplay.h \ libinterp/corefcn/comment-list.h \ libinterp/corefcn/data.h \ @@ -129,6 +130,7 @@ libinterp/corefcn/bitfcns.cc \ libinterp/corefcn/bsxfun.cc \ libinterp/corefcn/c-file-ptr-stream.cc \ + libinterp/corefcn/call-stack.cc \ libinterp/corefcn/cdisplay.c \ libinterp/corefcn/cellfun.cc \ libinterp/corefcn/colloc.cc \ diff -r 66db9a493c84 -r 0f6fc2ec3b1a libinterp/corefcn/octave-link.cc --- a/libinterp/corefcn/octave-link.cc Mon Jul 11 16:34:02 2016 -0400 +++ b/libinterp/corefcn/octave-link.cc Mon Jul 11 17:05:33 2016 -0400 @@ -30,6 +30,7 @@ #include "defun.h" #include "oct-env.h" #include "oct-mutex.h" +#include "pager.h" #include "singleton-cleanup.h" #include "toplev.h" diff -r 66db9a493c84 -r 0f6fc2ec3b1a libinterp/corefcn/toplev.cc --- a/libinterp/corefcn/toplev.cc Mon Jul 11 16:34:02 2016 -0400 +++ b/libinterp/corefcn/toplev.cc Mon Jul 11 17:05:33 2016 -0400 @@ -57,6 +57,7 @@ #include "build-env.h" #include "liboctinterp-build-info.h" +#include "call-stack.h" #include "defaults.h" #include "defun.h" #include "error.h" @@ -107,556 +108,6 @@ // TRUE means we've processed all the init code and we are good to go. bool octave_initialized = false; -octave_call_stack *octave_call_stack::instance = 0; - -std::string -octave_call_stack::stack_frame::fcn_file_name (void) const -{ - return m_fcn ? m_fcn->fcn_file_name () : ""; -} - -std::string -octave_call_stack::stack_frame::fcn_name (bool print_subfn) const -{ - std::string retval; - - if (m_fcn) - { - std::string parent_fcn_name = m_fcn->parent_fcn_name (); - - if (print_subfn && ! parent_fcn_name.empty ()) - retval = parent_fcn_name + Vfilemarker; - - retval += m_fcn->name (); - } - else - retval = ""; - - return retval; -} - -bool -octave_call_stack::stack_frame::operator== (const octave_call_stack::stack_frame &rhs) const -{ - if (this->line () != rhs.line ()) - return false; - else if (this->column () != rhs.column ()) - return false; - else if (this->fcn_file_name () != rhs.fcn_file_name ()) - return false; - else if (this->fcn_name () != rhs.fcn_name ()) - return false; - else - return true; -} - -void -octave_call_stack::create_instance (void) -{ - instance = new octave_call_stack (); - - if (instance) - { - instance->do_push (0, symbol_table::top_scope (), 0); - - singleton_cleanup_list::add (cleanup_instance); - } -} - -int -octave_call_stack::do_current_line (void) const -{ - int retval = -1; - - if (! cs.empty ()) - { - const stack_frame& elt = cs[curr_frame]; - retval = elt.m_line; - } - - return retval; -} - -int -octave_call_stack::do_current_column (void) const -{ - int retval = -1; - - if (! cs.empty ()) - { - const stack_frame& elt = cs[curr_frame]; - retval = elt.m_column; - } - - return retval; -} - -size_t -octave_call_stack::do_num_user_code_frames - (octave_idx_type& curr_user_frame) const -{ - size_t retval = 0; - - curr_user_frame = 0; - - // Look for the caller of dbstack. - size_t xframe = cs[curr_frame].m_prev; - - bool found = false; - - size_t k = cs.size (); - - for (const_reverse_iterator p = cs.rbegin (); p != cs.rend (); p++) - { - octave_function *f = (*p).m_fcn; - - if (--k == xframe) - found = true; - - if (f && f->is_user_code ()) - { - if (! found) - curr_user_frame++; - - retval++; - } - } - - // We counted how many user frames were not the one, in reverse. - // Now set curr_user_frame to be the index in the other direction. - curr_user_frame = retval - curr_user_frame - 1; - - return retval; -} - -octave_user_code * -octave_call_stack::do_caller_user_code (size_t nskip) const -{ - octave_user_code *retval = 0; - - const_iterator p = cs.end (); - - while (p != cs.begin ()) - { - const stack_frame& elt = *(--p); - - octave_function *f = elt.m_fcn; - - if (f && f->is_user_code ()) - { - if (nskip > 0) - nskip--; - else - { - retval = dynamic_cast (f); - break; - } - } - } - - return retval; -} - -int -octave_call_stack::do_caller_user_code_line (void) const -{ - int retval = -1; - - const_iterator p = cs.end (); - - while (p != cs.begin ()) - { - const stack_frame& elt = *(--p); - - octave_function *f = elt.m_fcn; - - if (f && f->is_user_code ()) - { - if (elt.m_line > 0) - { - retval = elt.m_line; - break; - } - } - } - - return retval; -} - -int -octave_call_stack::do_caller_user_code_column (void) const -{ - int retval = -1; - - const_iterator p = cs.end (); - - while (p != cs.begin ()) - { - const stack_frame& elt = *(--p); - - octave_function *f = elt.m_fcn; - - if (f && f->is_user_code ()) - { - if (elt.m_column) - { - retval = elt.m_column; - break; - } - } - } - - return retval; -} - -octave_user_code * -octave_call_stack::do_debug_user_code (void) const -{ - octave_user_code *retval = 0; - - // This should never happen... - if (curr_frame == 0) - return retval; - - // Start looking with the caller of the calling debug function. - size_t i = cs[curr_frame].m_prev; - - while (i != 0) - { - const stack_frame& elt = cs[i--]; - - octave_function *f = elt.m_fcn; - - if (f && f->is_user_code ()) - { - retval = dynamic_cast (f); - break; - } - } - - return retval; -} - -int -octave_call_stack::do_debug_user_code_line (void) const -{ - int retval = -1; - - // This should never happen... - if (curr_frame == 0) - return retval; - - // Start looking with the caller of the calling debug function. - size_t i = cs[curr_frame].m_prev; - - while (i != 0) - { - const stack_frame& elt = cs[i--]; - - octave_function *f = elt.m_fcn; - - if (f && f->is_user_code ()) - { - if (elt.m_line) - { - retval = elt.m_line; - break; - } - } - } - - return retval; -} - -int -octave_call_stack::do_debug_user_code_column (void) const -{ - int retval = -1; - - // This should never happen... - if (curr_frame == 0) - return retval; - - // Start looking with the caller of the calling debug function. - size_t i = cs[curr_frame].m_prev; - - while (i != 0) - { - const stack_frame& elt = cs[i--]; - - octave_function *f = elt.m_fcn; - - if (f && f->is_user_code ()) - { - if (elt.m_column) - { - retval = elt.m_column; - break; - } - } - } - - return retval; -} - -bool -octave_call_stack::do_all_scripts (void) const -{ - bool retval = true; - - const_iterator p = cs.end (); - - while (p != cs.begin ()) - { - const stack_frame& elt = *(--p); - - octave_function *f = elt.m_fcn; - - if (f && ! f->is_user_script ()) - { - retval = false; - break; - } - } - - return retval; -} - -// Use static fields for the best efficiency. -// NOTE: C++0x will allow these two to be merged into one. -static const char *bt_fieldnames[] = { "file", "name", "line", - "column", "scope", "context", 0 - }; -static const octave_fields bt_fields (bt_fieldnames); - -octave_map -octave_call_stack::empty_backtrace (void) -{ - return octave_map (dim_vector (0, 1), bt_fields); -} - -std::list -octave_call_stack::do_backtrace_frames (size_t nskip, - octave_idx_type& curr_user_frame) const -{ - std::list retval; - - size_t user_code_frames = do_num_user_code_frames (curr_user_frame); - - size_t nframes = nskip <= user_code_frames ? user_code_frames - nskip : 0; - - // Our list is reversed. - curr_user_frame = nframes - curr_user_frame - 1; - - if (nframes > 0) - { - for (const_reverse_iterator p = cs.rbegin (); p != cs.rend (); p++) - { - const stack_frame& elt = *p; - - octave_function *f = elt.m_fcn; - - if (f && f->is_user_code ()) - { - if (nskip > 0) - nskip--; - else - retval.push_back (elt); - } - } - } - - return retval; -} - -octave_map -octave_call_stack::do_backtrace (size_t nskip, - octave_idx_type& curr_user_frame, - bool print_subfn) const -{ - std::list frames - = do_backtrace_frames (nskip, curr_user_frame); - - size_t nframes = frames.size (); - - octave_map retval (dim_vector (nframes, 1), bt_fields); - - Cell& file = retval.contents (0); - Cell& name = retval.contents (1); - Cell& line = retval.contents (2); - Cell& column = retval.contents (3); - Cell& scope = retval.contents (4); - Cell& context = retval.contents (5); - - octave_idx_type k = 0; - - for (std::list::const_iterator p = frames.begin (); - p != frames.end (); p++) - { - const stack_frame& elt = *p; - - scope(k) = elt.m_scope; - context(k) = elt.m_context; - file(k) = elt.fcn_file_name (); - name(k) = elt.fcn_name (print_subfn); - line(k) = elt.m_line; - column(k) = elt.m_column; - - k++; - } - - return retval; -} - -bool -octave_call_stack::do_goto_frame (size_t n, bool verbose) -{ - bool retval = false; - - if (n < cs.size ()) - { - retval = true; - - curr_frame = n; - - const stack_frame& elt = cs[n]; - - symbol_table::set_scope_and_context (elt.m_scope, elt.m_context); - - if (verbose) - octave_stdout << "stopped in " << elt.fcn_name () - << " at line " << elt.m_line - << " column " << elt.m_column - << " [" << elt.fcn_file_name () << "] " - << " (scope = " << elt.m_scope - << "[context = " << elt.m_context << "])" - << std::endl; - } - - return retval; -} - -bool -octave_call_stack::do_goto_frame_relative (int nskip, bool verbose) -{ - bool retval = false; - - int incr = 0; - - if (nskip < 0) - incr = -1; - else if (nskip > 0) - incr = 1; - - // Start looking with the caller of dbup/dbdown/keyboard. - size_t xframe = cs[curr_frame].m_prev; - - while (true) - { - if ((incr < 0 && xframe == 0) || (incr > 0 && xframe == cs.size () - 1)) - break; - - xframe += incr; - - const stack_frame& elt = cs[xframe]; - - octave_function *f = elt.m_fcn; - - if (xframe == 0 || (f && f->is_user_code ())) - { - if (nskip > 0) - nskip--; - else if (nskip < 0) - nskip++; - - if (nskip == 0) - { - curr_frame = xframe; - cs[cs.size () - 1].m_prev = curr_frame; - - symbol_table::set_scope_and_context (elt.m_scope, elt.m_context); - - if (verbose) - { - std::ostringstream buf; - - if (f) - buf << "stopped in " << elt.fcn_name () - << " at line " << elt.m_line - << " [" << elt.fcn_file_name () << "] " - << std::endl; - else - buf << "at top level" << std::endl; - - octave_stdout << buf.str (); - } - - retval = true; - break; - } - } - else if (incr == 0) // Break out of infinite loop by choosing an incr. - incr = -1; - - // There is no need to set scope and context here. That will - // happen when the dbup/dbdown/keyboard frame is popped and we - // jump to the new "prev" frame set above. - } - - return retval; -} - -void -octave_call_stack::do_goto_caller_frame (void) -{ - size_t xframe = curr_frame; - - bool skipped = false; - - while (xframe != 0) - { - xframe = cs[xframe].m_prev; - - const stack_frame& elt = cs[xframe]; - - octave_function *f = elt.m_fcn; - - if (elt.m_scope == cs[0].m_scope || (f && f->is_user_code ())) - { - if (! skipped) - // We found the current user code frame, so skip it. - skipped = true; - else - { - // We found the caller user code frame. - stack_frame tmp (elt); - tmp.m_prev = curr_frame; - - curr_frame = cs.size (); - - cs.push_back (tmp); - - symbol_table::set_scope_and_context (tmp.m_scope, tmp.m_context); - - break; - } - } - } -} - -void -octave_call_stack::do_goto_base_frame (void) -{ - stack_frame tmp (cs[0]); - tmp.m_prev = curr_frame; - - curr_frame = cs.size (); - - cs.push_back (tmp); - - symbol_table::set_scope_and_context (tmp.m_scope, tmp.m_context); -} - void recover_from_exception (void) { diff -r 66db9a493c84 -r 0f6fc2ec3b1a libinterp/corefcn/toplev.h --- a/libinterp/corefcn/toplev.h Mon Jul 11 16:34:02 2016 -0400 +++ b/libinterp/corefcn/toplev.h Mon Jul 11 17:05:33 2016 -0400 @@ -25,25 +25,10 @@ #include "octave-config.h" -#include - -#include #include -class octave_value; -class octave_value_list; -class octave_function; -class octave_user_script; -class tree_statement; -class tree_statement_list; -class charMatrix; - #include "quit.h" -#include "input.h" -#include "oct-map.h" -#include "symtab.h" - typedef void (*octave_exit_func) (int); extern OCTINTERP_API octave_exit_func octave_exit; @@ -73,445 +58,6 @@ // TRUE means we've processed all the init code and we are good to go. extern OCTINTERP_API bool octave_initialized; -class -OCTINTERP_API -octave_call_stack -{ -protected: - - octave_call_stack (void) : cs (), curr_frame (0) { } - -public: - - class stack_frame - { - public: - - friend class octave_call_stack; - - stack_frame (octave_function *fcn = 0, symbol_table::scope_id scope = 0, - symbol_table::context_id context = 0, size_t prev = 0) - : m_fcn (fcn), m_line (-1), m_column (-1), m_scope (scope), - m_context (context), m_prev (prev) - { } - - stack_frame (const stack_frame& elt) - : m_fcn (elt.m_fcn), m_line (elt.m_line), m_column (elt.m_column), - m_scope (elt.m_scope), m_context (elt.m_context), m_prev (elt.m_prev) - { } - - int line (void) const { return m_line; } - - int column (void) const { return m_column; } - - std::string fcn_file_name (void) const; - - std::string fcn_name (bool print_subfn = true) const; - - bool operator== (const stack_frame &rhs) const; - - private: - - octave_function *m_fcn; - int m_line; - int m_column; - symbol_table::scope_id m_scope; - symbol_table::context_id m_context; - size_t m_prev; - }; - - typedef std::deque::iterator iterator; - typedef std::deque::const_iterator const_iterator; - - typedef std::deque::reverse_iterator reverse_iterator; - typedef std::deque::const_reverse_iterator const_reverse_iterator; - - static void create_instance (void); - - static bool instance_ok (void) - { - bool retval = true; - - if (! instance) - create_instance (); - - if (! instance) - error ("unable to create call stack object!"); - - return retval; - } - - // Current function (top of stack). - static octave_function *current (void) - { - return instance_ok () ? instance->do_current () : 0; - } - - // Current line in current function. - static int current_line (void) - { - return instance_ok () ? instance->do_current_line () : -1; - } - - // Current column in current function. - static int current_column (void) - { - return instance_ok () ? instance->do_current_column () : -1; - } - - // Caller function, may be built-in. - static octave_function *caller (void) - { - return instance_ok () ? instance->do_caller () : 0; - } - - static size_t current_frame (void) - { - return instance_ok () ? instance->do_current_frame () : 0; - } - - static size_t size (void) - { - return instance_ok () ? instance->do_size () : 0; - } - - static size_t num_user_code_frames (octave_idx_type& curr_user_frame) - { - return instance_ok () - ? instance->do_num_user_code_frames (curr_user_frame) : 0; - } - - static symbol_table::scope_id current_scope (void) - { - return instance_ok () ? instance->do_current_scope () : 0; - } - - static symbol_table::context_id current_context (void) - { - return instance_ok () ? instance->do_current_context () : 0; - } - -#if 0 - static stack_frame frame (size_t idx) - { - return instance_ok () ? instance->do_frame (idx) : stack_frame (); - } -#endif - - // Function at location N on the call stack (N == 0 is current), may - // be built-in. - static octave_function *element (size_t n) - { - return instance_ok () ? instance->do_element (n) : 0; - } - - // User code caller. - static octave_user_code *caller_user_code (size_t nskip = 0) - { - return instance_ok () ? instance->do_caller_user_code (nskip) : 0; - } - - // Line in user code caller. - static int caller_user_code_line (void) - { - return instance_ok () ? instance->do_caller_user_code_line () : -1; - } - - // Column in user code caller. - static int caller_user_code_column (void) - { - return instance_ok () ? instance->do_caller_user_code_column () : -1; - } - - // Current function that we are debugging. - static octave_user_code *debug_user_code (void) - { - return instance_ok () ? instance->do_debug_user_code () : 0; - } - - // Line number in current function that we are debugging. - static int debug_user_code_line (void) - { - return instance_ok () ? instance->do_debug_user_code_line () : 0; - } - - // Column number in current function that we are debugging. - static int debug_user_code_column (void) - { - return instance_ok () ? instance->do_debug_user_code_column () : 0; - } - - // Return TRUE if all elements on the call stack are scripts. - static bool all_scripts (void) - { - return instance_ok () ? instance->do_all_scripts () : false; - } - - static void - push (octave_function *f, - symbol_table::scope_id scope = symbol_table::current_scope (), - symbol_table::context_id context = symbol_table::current_context ()) - { - if (instance_ok ()) - instance->do_push (f, scope, context); - } - - static void - push (symbol_table::scope_id scope = symbol_table::current_scope (), - symbol_table::context_id context = symbol_table::current_context ()) - { - if (instance_ok ()) - instance->do_push (0, scope, context); - } - - static void set_location (int l, int c) - { - if (instance_ok ()) - instance->do_set_location (l, c); - } - - static void set_line (int l) - { - if (instance_ok ()) - instance->do_set_line (l); - } - - static void set_column (int c) - { - if (instance_ok ()) - instance->do_set_column (c); - } - - static bool goto_frame (size_t n = 0, bool verbose = false) - { - return instance_ok () ? instance->do_goto_frame (n, verbose) : false; - } - - static void restore_frame (size_t n) - { - goto_frame (n); - } - - static bool goto_frame_relative (int n, bool verbose = false) - { - return instance_ok () - ? instance->do_goto_frame_relative (n, verbose) : false; - } - - static void goto_caller_frame (void) - { - if (instance_ok ()) - instance->do_goto_caller_frame (); - } - - static void goto_base_frame (void) - { - if (instance_ok ()) - instance->do_goto_base_frame (); - } - - static octave_map backtrace (size_t nskip = 0) - { - octave_idx_type curr_user_frame = -1; - - return instance_ok () - ? instance->do_backtrace (nskip, curr_user_frame, true) - : octave_map (); - } - - static octave_map backtrace (size_t nskip, octave_idx_type& curr_user_frame, - bool print_subfn = true) - { - return instance_ok () - ? instance->do_backtrace (nskip, curr_user_frame, print_subfn) - : octave_map (); - } - - static std::list - backtrace_frames (size_t nskip = 0) - { - octave_idx_type curr_user_frame = -1; - - return instance_ok () - ? instance->do_backtrace_frames (nskip, curr_user_frame) - : std::list (); - } - - static std::list - backtrace_frames (size_t nskip, octave_idx_type& curr_user_frame) - { - return instance_ok () - ? instance->do_backtrace_frames (nskip, curr_user_frame) - : std::list (); - } - - static octave_map empty_backtrace (void); - - static void pop (void) - { - if (instance_ok ()) - instance->do_pop (); - } - - static void clear (void) - { - if (instance_ok ()) - instance->do_clear (); - } - -private: - - // The current call stack. - std::deque cs; - - size_t curr_frame; - - static octave_call_stack *instance; - - static void cleanup_instance (void) { delete instance; instance = 0; } - - int do_current_line (void) const; - - int do_current_column (void) const; - - octave_function *do_caller (void) const - { - return curr_frame > 1 ? cs[curr_frame-1].m_fcn : cs[0].m_fcn; - } - - size_t do_current_frame (void) { return curr_frame; } - - size_t do_size (void) { return cs.size (); } - - size_t do_num_user_code_frames (octave_idx_type& curr_user_frame) const; - - symbol_table::scope_id do_current_scope (void) const - { - return curr_frame > 0 && curr_frame < cs.size () - ? cs[curr_frame].m_scope : 0; - } - - symbol_table::context_id do_current_context (void) const - { - return curr_frame > 0 && curr_frame < cs.size () - ? cs[curr_frame].m_context : 0; - } - -#if 0 - const stack_frame& do_frame (size_t idx) - { - static stack_frame foobar; - - return idx < cs.size () ? cs[idx] : foobar; - } -#endif - - octave_function *do_element (size_t n) - { - octave_function *retval = 0; - - if (cs.size () > n) - { - stack_frame& elt = cs[n]; - retval = elt.m_fcn; - } - - return retval; - } - - octave_user_code *do_caller_user_code (size_t nskip) const; - int do_caller_user_code_line (void) const; - int do_caller_user_code_column (void) const; - - octave_user_code *do_debug_user_code (void) const; - int do_debug_user_code_line (void) const; - int do_debug_user_code_column (void) const; - - bool do_all_scripts (void) const; - - void do_push (octave_function *fcn, symbol_table::scope_id scope, - symbol_table::context_id context) - { - size_t prev_frame = curr_frame; - curr_frame = cs.size (); - cs.push_back (stack_frame (fcn, scope, context, prev_frame)); - symbol_table::set_scope_and_context (scope, context); - } - - octave_function *do_current (void) const - { - octave_function *retval = 0; - - if (! cs.empty ()) - { - const stack_frame& elt = cs[curr_frame]; - retval = elt.m_fcn; - } - - return retval; - } - - void do_set_location (int l, int c) - { - if (! cs.empty ()) - { - stack_frame& elt = cs.back (); - - elt.m_line = l; - elt.m_column = c; - } - } - - void do_set_line (int l) - { - if (! cs.empty ()) - { - stack_frame& elt = cs.back (); - - elt.m_line = l; - } - } - - void do_set_column (int c) - { - if (! cs.empty ()) - { - stack_frame& elt = cs.back (); - - elt.m_column = c; - } - } - - std::list - do_backtrace_frames (size_t nskip, octave_idx_type& curr_user_frame) const; - - octave_map do_backtrace (size_t nskip, - octave_idx_type& curr_user_frame, - bool print_subfn) const; - - bool do_goto_frame (size_t n, bool verbose); - - bool do_goto_frame_relative (int n, bool verbose); - - void do_goto_caller_frame (void); - - void do_goto_base_frame (void); - - void do_pop (void) - { - if (cs.size () > 1) - { - const stack_frame& elt = cs.back (); - curr_frame = elt.m_prev; - cs.pop_back (); - const stack_frame& new_elt = cs[curr_frame]; - symbol_table::set_scope_and_context (new_elt.m_scope, new_elt.m_context); - } - } - - void do_clear (void) { cs.clear (); } -}; - // Call a function with exceptions handled to avoid problems with // errors while shutting down. diff -r 66db9a493c84 -r 0f6fc2ec3b1a libinterp/corefcn/variables.cc --- a/libinterp/corefcn/variables.cc Mon Jul 11 16:34:02 2016 -0400 +++ b/libinterp/corefcn/variables.cc Mon Jul 11 17:05:33 2016 -0400 @@ -39,6 +39,7 @@ #include "lo-regexp.h" #include "str-vec.h" +#include "call-stack.h" #include #include "Cell.h" #include "defun.h" diff -r 66db9a493c84 -r 0f6fc2ec3b1a libinterp/octave-value/ov-base.cc --- a/libinterp/octave-value/ov-base.cc Mon Jul 11 16:34:02 2016 -0400 +++ b/libinterp/octave-value/ov-base.cc Mon Jul 11 17:05:33 2016 -0400 @@ -31,6 +31,7 @@ #include "lo-ieee.h" #include "lo-mappers.h" +#include "call-stack.h" #include "defun.h" #include "errwarn.h" #include "mxarray.h" diff -r 66db9a493c84 -r 0f6fc2ec3b1a libinterp/octave-value/ov-builtin.cc --- a/libinterp/octave-value/ov-builtin.cc Mon Jul 11 16:34:02 2016 -0400 +++ b/libinterp/octave-value/ov-builtin.cc Mon Jul 11 17:05:33 2016 -0400 @@ -24,6 +24,7 @@ # include "config.h" #endif +#include "call-stack.h" #include "error.h" #include "errwarn.h" #include "ovl.h" diff -r 66db9a493c84 -r 0f6fc2ec3b1a libinterp/octave-value/ov-class.cc --- a/libinterp/octave-value/ov-class.cc Mon Jul 11 16:34:02 2016 -0400 +++ b/libinterp/octave-value/ov-class.cc Mon Jul 11 17:05:33 2016 -0400 @@ -33,6 +33,7 @@ #include "lo-mappers.h" #include "Cell.h" +#include "call-stack.h" #include "defun.h" #include "error.h" #include "file-ops.h" diff -r 66db9a493c84 -r 0f6fc2ec3b1a libinterp/octave-value/ov-classdef.cc --- a/libinterp/octave-value/ov-classdef.cc Mon Jul 11 16:34:02 2016 -0400 +++ b/libinterp/octave-value/ov-classdef.cc Mon Jul 11 17:05:33 2016 -0400 @@ -26,6 +26,7 @@ #include +#include "call-stack.h" #include "defun.h" #include "load-path.h" #include "ov-builtin.h" diff -r 66db9a493c84 -r 0f6fc2ec3b1a libinterp/octave-value/ov-fcn-handle.cc --- a/libinterp/octave-value/ov-fcn-handle.cc Mon Jul 11 16:34:02 2016 -0400 +++ b/libinterp/octave-value/ov-fcn-handle.cc Mon Jul 11 17:05:33 2016 -0400 @@ -34,6 +34,7 @@ #include "file-ops.h" #include "oct-locbuf.h" +#include "call-stack.h" #include "defun.h" #include "error.h" #include "errwarn.h" diff -r 66db9a493c84 -r 0f6fc2ec3b1a libinterp/octave-value/ov-fcn-inline.cc --- a/libinterp/octave-value/ov-fcn-inline.cc Mon Jul 11 16:34:02 2016 -0400 +++ b/libinterp/octave-value/ov-fcn-inline.cc Mon Jul 11 17:05:33 2016 -0400 @@ -35,6 +35,7 @@ #include "oct-locbuf.h" +#include "call-stack.h" #include "defun.h" #include "error.h" #include "errwarn.h" diff -r 66db9a493c84 -r 0f6fc2ec3b1a libinterp/octave-value/ov-mex-fcn.cc --- a/libinterp/octave-value/ov-mex-fcn.cc Mon Jul 11 16:34:02 2016 -0400 +++ b/libinterp/octave-value/ov-mex-fcn.cc Mon Jul 11 17:05:33 2016 -0400 @@ -26,6 +26,7 @@ #include "oct-shlib.h" +#include "call-stack.h" #include #include "dynamic-ld.h" #include "error.h" diff -r 66db9a493c84 -r 0f6fc2ec3b1a libinterp/octave-value/ov-usr-fcn.cc --- a/libinterp/octave-value/ov-usr-fcn.cc Mon Jul 11 16:34:02 2016 -0400 +++ b/libinterp/octave-value/ov-usr-fcn.cc Mon Jul 11 17:05:33 2016 -0400 @@ -28,6 +28,7 @@ #include "str-vec.h" +#include "call-stack.h" #include #include "Cell.h" #include "builtins.h" diff -r 66db9a493c84 -r 0f6fc2ec3b1a libinterp/parse-tree/oct-parse.in.yy --- a/libinterp/parse-tree/oct-parse.in.yy Mon Jul 11 16:34:02 2016 -0400 +++ b/libinterp/parse-tree/oct-parse.in.yy Mon Jul 11 17:05:33 2016 -0400 @@ -43,7 +43,6 @@ #include #include -#include "Cell.h" #include "Matrix.h" #include "cmd-edit.h" #include "cmd-hist.h" @@ -53,6 +52,8 @@ #include "oct-time.h" #include "quit.h" +#include "Cell.h" +#include "call-stack.h" #include "comment-list.h" #include "defaults.h" #include "defun.h" diff -r 66db9a493c84 -r 0f6fc2ec3b1a libinterp/parse-tree/pt-eval.cc --- a/libinterp/parse-tree/pt-eval.cc Mon Jul 11 16:34:02 2016 -0400 +++ b/libinterp/parse-tree/pt-eval.cc Mon Jul 11 17:05:33 2016 -0400 @@ -31,6 +31,7 @@ #include #include +#include "call-stack.h" #include "debug.h" #include "defun.h" #include "error.h" diff -r 66db9a493c84 -r 0f6fc2ec3b1a libinterp/parse-tree/pt-fcn-handle.cc --- a/libinterp/parse-tree/pt-fcn-handle.cc Mon Jul 11 16:34:02 2016 -0400 +++ b/libinterp/parse-tree/pt-fcn-handle.cc Mon Jul 11 17:05:33 2016 -0400 @@ -26,6 +26,7 @@ #include +#include "call-stack.h" #include "error.h" #include "ovl.h" #include "ov-fcn-handle.h" diff -r 66db9a493c84 -r 0f6fc2ec3b1a libinterp/parse-tree/pt-mat.cc --- a/libinterp/parse-tree/pt-mat.cc Mon Jul 11 16:34:02 2016 -0400 +++ b/libinterp/parse-tree/pt-mat.cc Mon Jul 11 17:05:33 2016 -0400 @@ -33,6 +33,7 @@ #include "defun.h" #include "error.h" #include "errwarn.h" +#include "oct-map.h" #include "ovl.h" #include "pt-arg-list.h" #include "pt-bp.h"