Go to the documentation of this file.00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019
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
00071 extern OCTINTERP_API tree_statement_list *global_command;
00072
00073
00074
00075 extern OCTINTERP_API bool octave_interpreter_ready;
00076
00077
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
00135 static octave_function *current (void)
00136 {
00137 return instance_ok () ? instance->do_current () : 0;
00138 }
00139
00140
00141 static tree_statement *current_statement (void)
00142 {
00143 return instance_ok () ? instance->do_current_statement () : 0;
00144 }
00145
00146
00147 static int current_line (void)
00148 {
00149 return instance_ok () ? instance->do_current_line () : -1;
00150 }
00151
00152
00153 static int current_column (void)
00154 {
00155 return instance_ok () ? instance->do_current_column () : -1;
00156 }
00157
00158
00159 static int caller_user_code_line (void)
00160 {
00161 return instance_ok () ? instance->do_caller_user_code_line () : -1;
00162 }
00163
00164
00165 static int caller_user_code_column (void)
00166 {
00167 return instance_ok () ? instance->do_caller_user_code_column () : -1;
00168 }
00169
00170
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
00203
00204 static octave_function *element (size_t n)
00205 {
00206 return instance_ok () ? instance->do_element (n) : 0;
00207 }
00208
00209
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
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
00422
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