toplev.h

Go to the documentation of this file.
00001 /*
00002 
00003 Copyright (C) 1993-2012 John W. Eaton
00004 
00005 This file is part of Octave.
00006 
00007 Octave is free software; you can redistribute it and/or modify it
00008 under the terms of the GNU General Public License as published by the
00009 Free Software Foundation; either version 3 of the License, or (at your
00010 option) any later version.
00011 
00012 Octave is distributed in the hope that it will be useful, but WITHOUT
00013 ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
00014 FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
00015 for more details.
00016 
00017 You should have received a copy of the GNU General Public License
00018 along with Octave; see the file COPYING.  If not, see
00019 <http://www.gnu.org/licenses/>.
00020 
00021 */
00022 
00023 #if !defined (octave_toplev_h)
00024 #define octave_toplev_h 1
00025 
00026 #include <cstdio>
00027 
00028 #include <deque>
00029 #include <string>
00030 
00031 class octave_value;
00032 class octave_value_list;
00033 class octave_function;
00034 class octave_user_script;
00035 class tree_statement;
00036 class tree_statement_list;
00037 class charMatrix;
00038 
00039 #include "quit.h"
00040 
00041 #include "input.h"
00042 #include "oct-map.h"
00043 
00044 
00045 typedef void (*octave_exit_func) (int);
00046 extern OCTINTERP_API octave_exit_func octave_exit;
00047 
00048 extern OCTINTERP_API bool quit_allowed;
00049 
00050 extern OCTINTERP_API bool quitting_gracefully;
00051 
00052 extern OCTINTERP_API int exit_status;
00053 
00054 extern OCTINTERP_API void
00055 clean_up_and_exit (int);
00056 
00057 extern OCTINTERP_API void recover_from_exception (void);
00058 
00059 extern OCTINTERP_API int main_loop (void);
00060 
00061 extern OCTINTERP_API void
00062 do_octave_atexit (void);
00063 
00064 extern OCTINTERP_API void
00065 octave_add_atexit_function (const std::string& fname);
00066 
00067 extern OCTINTERP_API bool
00068 octave_remove_atexit_function (const std::string& fname);
00069 
00070 // Current command to execute.
00071 extern OCTINTERP_API tree_statement_list *global_command;
00072 
00073 // TRUE means we are ready to interpret commands, but not everything
00074 // is ready for interactive use.
00075 extern OCTINTERP_API bool octave_interpreter_ready;
00076 
00077 // TRUE means we've processed all the init code and we are good to go.
00078 extern OCTINTERP_API bool octave_initialized;
00079 
00080 class
00081 OCTINTERP_API
00082 octave_call_stack
00083 {
00084 private:
00085 
00086   struct call_stack_elt
00087   {
00088     call_stack_elt (octave_function *f, symbol_table::scope_id s,
00089                     symbol_table::context_id c, size_t p = 0)
00090       : fcn (f), stmt (0), scope (s), context (c), prev (p) { }
00091 
00092     call_stack_elt (const call_stack_elt& elt)
00093       : fcn (elt.fcn), stmt (elt.stmt), scope (elt.scope),
00094         context (elt.context), prev (elt.prev) { }
00095 
00096     octave_function *fcn;
00097     tree_statement *stmt;
00098     symbol_table::scope_id scope;
00099     symbol_table::context_id context;
00100     size_t prev;
00101   };
00102 
00103 protected:
00104 
00105   octave_call_stack (void) : cs (), curr_frame (0) { }
00106 
00107 public:
00108 
00109   typedef std::deque<call_stack_elt>::iterator iterator;
00110   typedef std::deque<call_stack_elt>::const_iterator const_iterator;
00111 
00112   typedef std::deque<call_stack_elt>::reverse_iterator reverse_iterator;
00113   typedef std::deque<call_stack_elt>::const_reverse_iterator const_reverse_iterator;
00114 
00115   static void create_instance (void);
00116   
00117   static bool instance_ok (void)
00118   {
00119     bool retval = true;
00120 
00121     if (! instance)
00122       create_instance ();
00123 
00124     if (! instance)
00125       {
00126         ::error ("unable to create call stack object!");
00127 
00128         retval = false;
00129       }
00130 
00131     return retval;
00132   }
00133 
00134   // Current function (top of stack).
00135   static octave_function *current (void)
00136   {
00137     return instance_ok () ? instance->do_current () : 0;
00138   }
00139 
00140   // Current statement (top of stack).
00141   static tree_statement *current_statement (void)
00142   {
00143     return instance_ok () ? instance->do_current_statement () : 0;
00144   }
00145 
00146   // Current line in current function.
00147   static int current_line (void)
00148   {
00149     return instance_ok () ? instance->do_current_line () : -1;
00150   }
00151 
00152   // Current column in current function.
00153   static int current_column (void)
00154   {
00155     return instance_ok () ? instance->do_current_column () : -1;
00156   }
00157 
00158   // Line in user code caller.
00159   static int caller_user_code_line (void)
00160   {
00161     return instance_ok () ? instance->do_caller_user_code_line () : -1;
00162   }
00163 
00164   // Column in user code caller.
00165   static int caller_user_code_column (void)
00166   {
00167     return instance_ok () ? instance->do_caller_user_code_column () : -1;
00168   }
00169 
00170   // Caller function, may be built-in.
00171   static octave_function *caller (void)
00172   {
00173     return instance_ok () ? instance->do_caller () : 0;
00174   }
00175 
00176   static size_t current_frame (void)
00177   {
00178     return instance_ok () ? instance->do_current_frame () : 0;
00179   }
00180 
00181   static size_t size (void)
00182   {
00183     return instance_ok () ? instance->do_size () : 0;
00184   }
00185 
00186   static size_t num_user_code_frames (octave_idx_type& curr_user_frame)
00187   {
00188     return instance_ok ()
00189       ? instance->do_num_user_code_frames (curr_user_frame) : 0;
00190   }
00191 
00192   static symbol_table::scope_id current_scope (void)
00193   {
00194     return instance_ok () ? instance->do_current_scope () : 0;
00195   }
00196 
00197   static symbol_table::context_id current_context (void)
00198   {
00199     return instance_ok () ? instance->do_current_context () : 0;
00200   }
00201 
00202   // Function at location N on the call stack (N == 0 is current), may
00203   // be built-in.
00204   static octave_function *element (size_t n)
00205   {
00206     return instance_ok () ? instance->do_element (n) : 0;
00207   }
00208 
00209   // First user-defined function on the stack.
00210   static octave_user_code *caller_user_code (size_t nskip = 0)
00211   {
00212     return instance_ok () ? instance->do_caller_user_code (nskip) : 0;
00213   }
00214 
00215   static void
00216   push (octave_function *f,
00217         symbol_table::scope_id scope = symbol_table::current_scope (),
00218         symbol_table::context_id context = symbol_table::current_context ())
00219   {
00220     if (instance_ok ())
00221       instance->do_push (f, scope, context);
00222   }
00223 
00224   static void
00225   push (symbol_table::scope_id scope = symbol_table::current_scope (),
00226         symbol_table::context_id context = symbol_table::current_context ())
00227   {
00228     if (instance_ok ())
00229       instance->do_push (0, scope, context);
00230   }
00231 
00232   static void set_statement (tree_statement *s)
00233   {
00234     if (instance_ok ())
00235       instance->do_set_statement (s);
00236   }
00237 
00238   static bool goto_frame (size_t n = 0, bool verbose = false)
00239   {
00240     return instance_ok () ? instance->do_goto_frame (n, verbose) : false;
00241   }
00242 
00243   static void restore_frame (size_t n)
00244   {
00245     goto_frame (n);
00246   }
00247 
00248   static bool goto_frame_relative (int n, bool verbose = false)
00249   {
00250     return instance_ok ()
00251       ? instance->do_goto_frame_relative (n, verbose) : false;
00252   }
00253 
00254   static void goto_caller_frame (void)
00255   {
00256     if (instance_ok ())
00257       instance->do_goto_caller_frame ();
00258   }
00259 
00260   static void goto_base_frame (void)
00261   {
00262     if (instance_ok ())
00263       instance->do_goto_base_frame ();
00264   }
00265 
00266   static octave_map backtrace (size_t nskip, octave_idx_type& curr_user_frame)
00267   {
00268     return instance_ok ()
00269       ? instance->do_backtrace (nskip, curr_user_frame) : octave_map ();
00270   }
00271 
00272   static octave_map empty_backtrace (void);
00273 
00274   static void pop (void)
00275   {
00276     if (instance_ok ())
00277       instance->do_pop ();
00278   }
00279 
00280   static void clear (void)
00281   {
00282     if (instance_ok ())
00283       instance->do_clear ();
00284   }
00285 
00286   static void backtrace_error_message (void)
00287   {
00288     if (instance_ok ())
00289       instance->do_backtrace_error_message ();
00290   }
00291 
00292 private:
00293 
00294   // The current call stack.
00295   std::deque<call_stack_elt> cs;
00296 
00297   size_t curr_frame;
00298 
00299   static octave_call_stack *instance;
00300 
00301   static void cleanup_instance (void) { delete instance; instance = 0; }
00302 
00303   int do_current_line (void) const;
00304 
00305   int do_current_column (void) const;
00306 
00307   int do_caller_user_code_line (void) const;
00308 
00309   int do_caller_user_code_column (void) const;
00310 
00311   octave_function *do_caller (void) const
00312   {
00313     return curr_frame > 1 ? cs[curr_frame-1].fcn : cs[0].fcn;
00314   }
00315 
00316   size_t do_current_frame (void) { return curr_frame; }
00317 
00318   size_t do_size (void) { return cs.size (); }
00319 
00320   size_t do_num_user_code_frames (octave_idx_type& curr_user_frame) const;
00321 
00322   symbol_table::scope_id do_current_scope (void) const
00323   {
00324     return curr_frame > 0 && curr_frame < cs.size ()
00325       ? cs[curr_frame].scope : 0;
00326   }
00327 
00328   symbol_table::context_id do_current_context (void) const
00329   {
00330     return curr_frame > 0 && curr_frame < cs.size ()
00331       ? cs[curr_frame].context : 0;
00332   }
00333 
00334   octave_function *do_element (size_t n)
00335   {
00336     octave_function *retval = 0;
00337 
00338     if (cs.size () > n)
00339       {
00340         call_stack_elt& elt = cs[n];
00341         retval = elt.fcn;
00342       }
00343 
00344     return retval;
00345   }
00346 
00347   octave_user_code *do_caller_user_code (size_t nskip) const;
00348 
00349   void do_push (octave_function *f, symbol_table::scope_id scope,
00350                 symbol_table::context_id context)
00351   {
00352     size_t prev_frame = curr_frame;
00353     curr_frame = cs.size ();
00354     cs.push_back (call_stack_elt (f, scope, context, prev_frame));
00355     symbol_table::set_scope_and_context (scope, context);
00356   }
00357 
00358   octave_function *do_current (void) const
00359   {
00360     octave_function *retval = 0;
00361 
00362     if (! cs.empty ())
00363       {
00364         const call_stack_elt& elt = cs[curr_frame];
00365         retval = elt.fcn;
00366       }
00367 
00368     return retval;
00369   }
00370 
00371   tree_statement *do_current_statement (void) const
00372   {
00373     tree_statement *retval = 0;
00374 
00375     if (! cs.empty ())
00376       {
00377         const call_stack_elt& elt = cs[curr_frame];
00378         retval = elt.stmt;
00379       }
00380 
00381     return retval;
00382   }
00383 
00384   void do_set_statement (tree_statement *s)
00385   {
00386     if (! cs.empty ())
00387       {
00388         call_stack_elt& elt = cs.back ();
00389         elt.stmt = s;
00390       }
00391   }
00392 
00393   octave_map do_backtrace (size_t nskip,
00394                            octave_idx_type& curr_user_frame) const;
00395 
00396   bool do_goto_frame (size_t n, bool verbose);
00397 
00398   bool do_goto_frame_relative (int n, bool verbose);
00399 
00400   void do_goto_caller_frame (void);
00401 
00402   void do_goto_base_frame (void);
00403 
00404   void do_pop (void)
00405   {
00406     if (cs.size () > 1)
00407       {
00408         const call_stack_elt& elt = cs.back ();
00409         curr_frame = elt.prev;
00410         cs.pop_back ();
00411         const call_stack_elt& new_elt = cs[curr_frame];
00412         symbol_table::set_scope_and_context (new_elt.scope, new_elt.context);
00413       }
00414   }
00415 
00416   void do_clear (void) { cs.clear (); }
00417 
00418   void do_backtrace_error_message (void) const;
00419 };
00420 
00421 // Call a function with exceptions handled to avoid problems with
00422 // errors while shutting down.
00423 
00424 #define OCTAVE_IGNORE_EXCEPTION(E) \
00425   catch (E) \
00426     { \
00427       std::cerr << "error: ignoring " #E " while preparing to exit" << std::endl; \
00428       recover_from_exception (); \
00429     }
00430 
00431 #define OCTAVE_SAFE_CALL(F, ARGS) \
00432   do \
00433     { \
00434       try \
00435         { \
00436           unwind_protect frame; \
00437  \
00438           frame.protect_var (Vdebug_on_error); \
00439           frame.protect_var (Vdebug_on_warning); \
00440  \
00441           Vdebug_on_error = false; \
00442           Vdebug_on_warning = false; \
00443  \
00444           F ARGS; \
00445         } \
00446       OCTAVE_IGNORE_EXCEPTION (octave_interrupt_exception) \
00447       OCTAVE_IGNORE_EXCEPTION (octave_execution_exception) \
00448       OCTAVE_IGNORE_EXCEPTION (std::bad_alloc) \
00449  \
00450       if (error_state) \
00451         error_state = 0; \
00452     } \
00453   while (0)
00454 
00455 #endif
 All Classes Files Functions Variables Typedefs Enumerations Enumerator Friends Defines