Mercurial > hg > octave-nkf
changeset 7734:2dee19385d32
eliminate tree_statement_stack; handle current statement info in octave_call_stack
author | John W. Eaton <jwe@octave.org> |
---|---|
date | Fri, 25 Apr 2008 12:16:42 -0400 |
parents | bb614b3883a9 |
children | 6848970153ba |
files | src/ChangeLog src/error.cc src/input.cc src/pt-stmt.cc src/pt-stmt.h src/toplev.cc src/toplev.h |
diffstat | 7 files changed, 246 insertions(+), 132 deletions(-) [+] |
line wrap: on
line diff
--- a/src/ChangeLog +++ b/src/ChangeLog @@ -1,3 +1,31 @@ +2008-04-25 John W. Eaton <jwe@octave.org> + + * error.cc (verror, pr_where): Use octave_call_stack instead of + tree_statement stack to get line and column information. + (pr_where): Use octave_call_stack instead of tree_statement stack + to get current statement. + * input.cc (get_user_input): Extract current line number from + octave_call_stack instead of tree_statement_stack. + * pt-stmt.cc (tree_statement::eval): Put current statement on + octave_call_stack instead of tree_statement_stack. + * pt-stmt.h, pt-stmt.cc (class tree_statement_stack): Delete. + + * toplev.h, toplev.cc (octave_call_stack::call_stack_elt): + New nested struct. + (octave_call_stack::cs): Now a deque of call_stack_elts. + Change all uses. + (octave_call_stack::current_statement, + octave_call_stack::current_line, + octave_call_stack::current_column, + octave_call_stack::top_statement, + octave_call_stack::set_statement, octave_call_stack::backtrace): + New static functions. + (octave_call_stack::do_current_line, + octave_call_stack::do_current_column, + octave_call_stack::do_top_statement, + octave_call_stack::do_set_statement, + octave_call_stack::do_backtrace): New member functions. + 2008-04-24 John W. Eaton <jwe@octave.org> * toplev.h, toplev.cc (octave_call_stack::unwind_pop_script):
--- a/src/error.cc +++ b/src/error.cc @@ -232,7 +232,7 @@ Vlast_error_name = std::string (); Vlast_error_file = std::string (); - if (tree_statement_stack::current ()) + if (octave_call_stack::current_statement ()) { octave_user_code *fcn = octave_call_stack::caller_user_code (); @@ -240,8 +240,8 @@ { Vlast_error_file = fcn->fcn_file_name (); Vlast_error_name = fcn->name(); - Vlast_error_line = tree_statement_stack::current_line (); - Vlast_error_column = tree_statement_stack::current_column (); + Vlast_error_line = octave_call_stack::current_line (); + Vlast_error_column = octave_call_stack::current_column (); } } } @@ -421,7 +421,7 @@ static void pr_where (const char *name, bool print_code = true) { - if (tree_statement_stack::current ()) + if (octave_call_stack::current_statement ()) { std::string nm; @@ -437,8 +437,8 @@ if (nm.empty ()) nm = fcn->name (); - l = tree_statement_stack::current_line (); - c = tree_statement_stack::current_column (); + l = octave_call_stack::current_line (); + c = octave_call_stack::current_column (); } if (nm.empty ()) @@ -469,7 +469,7 @@ tree_print_code tpc (output_buf, ">>> "); - tree_statement *curr_stmt = tree_statement_stack::current (); + tree_statement *curr_stmt = octave_call_stack::current_statement (); if (curr_stmt) curr_stmt->accept (tpc);
--- a/src/input.cc +++ b/src/input.cc @@ -607,7 +607,7 @@ if (nm.empty ()) nm = caller->name (); - line = tree_statement_stack::current_line (); + line = octave_call_stack::current_line (); } } @@ -699,7 +699,7 @@ { tree::break_next = true; - tree::last_line = tree_statement_stack::current_line (); + tree::last_line = octave_call_stack::current_line (); tree::break_function = octave_call_stack::current ();
--- a/src/pt-stmt.cc +++ b/src/pt-stmt.cc @@ -87,8 +87,7 @@ if (cmd || expr) { - unwind_protect::add (tree_statement_stack::unwind_pop, 0); - tree_statement_stack::push (this); + octave_call_stack::set_statement (this); maybe_echo_code (in_function_body); @@ -131,8 +130,6 @@ octave_exception_state = octave_no_exception; error ("caught execution error in library function"); } - - unwind_protect::run (); } return retval; @@ -285,8 +282,6 @@ tw.visit_statement_list (*this); } -tree_statement_stack *tree_statement_stack::instance = 0; - /* ;;; Local Variables: *** ;;; mode: C++ ***
--- a/src/pt-stmt.h +++ b/src/pt-stmt.h @@ -160,106 +160,6 @@ tree_statement_list& operator = (const tree_statement_list&); }; -class tree_statement_stack -{ -protected: - - tree_statement_stack (void) : tss () { } - -public: - - typedef std::deque<tree_statement *>::iterator iterator ; - - static bool instance_ok (void) - { - bool retval = true; - - if (! instance) - instance = new tree_statement_stack (); - - if (! instance) - { - ::error ("unable to create stmt stack object!"); - - retval = false; - } - - return retval; - } - - // Current statement (top of stack). - static tree_statement *current (void) { return top (); } - - static int current_line (void) - { - tree_statement *s = current (); - return s ? s->line () : -1; - } - - static int current_column (void) - { - tree_statement *s = current (); - return s ? s->column () : -1; - } - - // Statement at position N on the call stack (N == 0 is current). - static tree_statement *element (size_t n) - { - return instance_ok () ? instance->do_element (n) : 0; - } - - // Caller statement - static tree_statement *caller (void) { return element (1); } - - static void push (tree_statement *f) - { - if (instance_ok ()) - instance->do_push (f); - } - - static tree_statement *top (void) - { - return instance_ok () ? instance->do_top (): 0; - } - - static void pop (void) - { - if (instance_ok ()) - instance->do_pop (); - } - - // A function for popping the top of the call stack that is suitable - // for use as an unwind_protect handler. - static void unwind_pop (void *) { pop (); } - - static void clear (void) - { - if (instance_ok ()) - instance->do_clear (); - } - -private: - - // The current stmt stack. - std::deque<tree_statement *> tss; - - static tree_statement_stack *instance; - - tree_statement *do_element (size_t n) { return tss.size () > n ? tss[n] : 0; } - - void do_push (tree_statement *f) { tss.push_front (f); } - - tree_statement *do_top (void) { return tss.empty () ? 0 : tss.front (); } - - void do_pop (void) - { - if (! tss.empty ()) - tss.pop_front (); - } - - void do_clear (void) { tss.clear (); } -}; - #endif /*
--- a/src/toplev.cc +++ b/src/toplev.cc @@ -95,14 +95,32 @@ octave_call_stack *octave_call_stack::instance = 0; +int +octave_call_stack::do_current_line (void) const +{ + tree_statement *stmt = do_top_statement (); + + return stmt ? stmt->line () : -1; +} + +int +octave_call_stack::do_current_column (void) const +{ + tree_statement *stmt = do_top_statement (); + + return stmt ? stmt->column () : -1; +} + octave_user_script * -octave_call_stack::do_caller_user_script (void) +octave_call_stack::do_caller_user_script (void) const { octave_user_script *retval = 0; - for (iterator p = cs.begin (); p != cs.end (); p++) + for (const_iterator p = cs.begin (); p != cs.end (); p++) { - octave_function *f = *p; + const call_stack_elt& elt = *p; + + octave_function *f = elt.fcn; if (f && f->is_user_script ()) { @@ -115,13 +133,15 @@ } octave_user_function * -octave_call_stack::do_caller_user_function (void) +octave_call_stack::do_caller_user_function (void) const { octave_user_function *retval = 0; - for (iterator p = cs.begin (); p != cs.end (); p++) + for (const_iterator p = cs.begin (); p != cs.end (); p++) { - octave_function *f = *p; + const call_stack_elt& elt = *p; + + octave_function *f = elt.fcn; if (f && f->is_user_function ()) { @@ -134,13 +154,15 @@ } octave_user_code * -octave_call_stack::do_caller_user_code (void) +octave_call_stack::do_caller_user_code (void) const { octave_user_code *retval = 0; - for (iterator p = cs.begin (); p != cs.end (); p++) + for (const_iterator p = cs.begin (); p != cs.end (); p++) { - octave_function *f = *p; + const call_stack_elt& elt = *p; + + octave_function *f = elt.fcn; if (f && f->is_user_code ()) { @@ -152,6 +174,77 @@ return retval; } +Octave_map +octave_call_stack::do_backtrace (void) const +{ + Octave_map retval; + + size_t nframes = cs.size () - 1; + + Cell keys (4, 1); + + keys(0) = "file"; + keys(1) = "name"; + keys(2) = "line"; + keys(3) = "column"; + + Cell file (nframes, 1); + Cell name (nframes, 1); + Cell line (nframes, 1); + Cell column (nframes, 1); + + const_iterator p = cs.begin (); + + // Skip innermost function as it will be the dbstatus function + // itself. FIXME -- Is it best to do this here? + p++; + + octave_idx_type k = 0; + + while (p != cs.end ()) + { + const call_stack_elt& elt = *p; + + octave_function *f = elt.fcn; + + if (f) + { + file(k) = f->fcn_file_name (); + name(k) = f->name (); + + tree_statement *stmt = elt.stmt; + + if (stmt) + { + line(k) = stmt->line (); + column(k) = stmt->column (); + } + else + { + line(k) = -1; + column(k) = -1; + } + } + else + { + file(k) = "<unknown>"; + name(k) = "<unknown>"; + line(k) = -1; + column(k) = -1; + } + + k++; + p++; + } + + retval.assign ("file", file); + retval.assign ("name", name); + retval.assign ("line", line); + retval.assign ("column", column); + + return retval; +} + void recover_from_exception (void) {
--- a/src/toplev.h +++ b/src/toplev.h @@ -33,9 +33,12 @@ class octave_value_list; class octave_function; class octave_user_script; +class tree_statement; class tree_statement_list; class charMatrix; +#include "oct-map.h" + extern OCTINTERP_API void clean_up_and_exit (int) GCC_ATTR_NORETURN; @@ -68,13 +71,24 @@ class octave_call_stack { +private: + + struct call_stack_elt + { + call_stack_elt (octave_function *f) : fcn (f), stmt (0) { } + + octave_function *fcn; + tree_statement *stmt; + }; + protected: octave_call_stack (void) : cs () { } public: - typedef std::deque<octave_function *>::iterator iterator ; + typedef std::deque<call_stack_elt>::iterator iterator; + typedef std::deque<call_stack_elt>::const_iterator const_iterator; static bool instance_ok (void) { @@ -96,6 +110,21 @@ // Current function (top of stack). static octave_function *current (void) { return top (); } + // Current statement (top of stack). + static tree_statement *current_statement (void) { return top_statement (); } + + // Current line in current function. + static int current_line (void) + { + return instance_ok () ? instance->do_current_line () : 0; + } + + // Current column in current function. + static int current_column (void) + { + return instance_ok () ? instance->do_current_column () : 0; + } + // Caller function, may be built-in. static octave_function *caller (void) { @@ -138,6 +167,22 @@ return instance_ok () ? instance->do_top (): 0; } + static tree_statement *top_statement (void) + { + return instance_ok () ? instance->do_top_statement (): 0; + } + + static void set_statement (tree_statement *s) + { + if (instance_ok ()) + instance->do_set_statement (s); + } + + static Octave_map backtrace (void) + { + return instance_ok () ? instance->do_backtrace () : Octave_map (); + } + static void pop (void) { if (instance_ok ()) @@ -157,21 +202,74 @@ private: // The current call stack. - std::deque<octave_function *> cs; + std::deque<call_stack_elt> cs; static octave_call_stack *instance; - octave_function *do_element (size_t n) { return cs.size () > n ? cs[n] : 0; } + int do_current_line (void) const; + + int do_current_column (void) const; + + octave_function *do_element (size_t n) + { + octave_function *retval = 0; + + if (cs.size () > n) + { + call_stack_elt& elt = cs[n]; + retval = elt.fcn; + } - octave_user_script *do_caller_user_script (void); + return retval; + } + + octave_user_script *do_caller_user_script (void) const; + + octave_user_function *do_caller_user_function (void) const; + + octave_user_code *do_caller_user_code (void) const; - octave_user_function *do_caller_user_function (void); + void do_push (octave_function *f) + { + cs.push_front (call_stack_elt (f)); + } + + octave_function *do_top (void) const + { + octave_function *retval = 0; - octave_user_code *do_caller_user_code (void); + if (! cs.empty ()) + { + const call_stack_elt& elt = cs.front (); + retval = elt.fcn; + } + + return retval; + } + + tree_statement *do_top_statement (void) const + { + tree_statement *retval = 0; - void do_push (octave_function *f) { cs.push_front (f); } + if (! cs.empty ()) + { + const call_stack_elt& elt = cs.front (); + retval = elt.stmt; + } + + return retval; + } - octave_function *do_top (void) { return cs.empty () ? 0 : cs.front (); } + void do_set_statement (tree_statement *s) + { + if (! cs.empty ()) + { + call_stack_elt& elt = cs.front (); + elt.stmt = s; + } + } + + Octave_map do_backtrace (void) const; void do_pop (void) {