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 bool instance_ok (void)
00116 {
00117 bool retval = true;
00118
00119 if (! instance)
00120 {
00121 instance = new octave_call_stack ();
00122
00123 if (instance)
00124 instance->do_push (0, symbol_table::top_scope (), 0);
00125 else
00126 {
00127 ::error ("unable to create call stack object!");
00128
00129 retval = false;
00130 }
00131 }
00132
00133 return retval;
00134 }
00135
00136
00137 static octave_function *current (void)
00138 {
00139 return instance_ok () ? instance->do_current () : 0;
00140 }
00141
00142
00143 static tree_statement *current_statement (void)
00144 {
00145 return instance_ok () ? instance->do_current_statement () : 0;
00146 }
00147
00148
00149 static int current_line (void)
00150 {
00151 return instance_ok () ? instance->do_current_line () : -1;
00152 }
00153
00154
00155 static int current_column (void)
00156 {
00157 return instance_ok () ? instance->do_current_column () : -1;
00158 }
00159
00160
00161 static int caller_user_code_line (void)
00162 {
00163 return instance_ok () ? instance->do_caller_user_code_line () : -1;
00164 }
00165
00166
00167 static int caller_user_code_column (void)
00168 {
00169 return instance_ok () ? instance->do_caller_user_code_column () : -1;
00170 }
00171
00172
00173 static octave_function *caller (void)
00174 {
00175 return instance_ok () ? instance->do_caller () : 0;
00176 }
00177
00178 static size_t current_frame (void)
00179 {
00180 return instance_ok () ? instance->do_current_frame () : 0;
00181 }
00182
00183 static size_t size (void)
00184 {
00185 return instance_ok () ? instance->do_size () : 0;
00186 }
00187
00188 static size_t num_user_code_frames (octave_idx_type& curr_user_frame)
00189 {
00190 return instance_ok ()
00191 ? instance->do_num_user_code_frames (curr_user_frame) : 0;
00192 }
00193
00194 static symbol_table::scope_id current_scope (void)
00195 {
00196 return instance_ok () ? instance->do_current_scope () : 0;
00197 }
00198
00199 static symbol_table::context_id current_context (void)
00200 {
00201 return instance_ok () ? instance->do_current_context () : 0;
00202 }
00203
00204
00205
00206 static octave_function *element (size_t n)
00207 {
00208 return instance_ok () ? instance->do_element (n) : 0;
00209 }
00210
00211
00212 static octave_user_code *caller_user_code (size_t nskip = 0)
00213 {
00214 return instance_ok () ? instance->do_caller_user_code (nskip) : 0;
00215 }
00216
00217 static void
00218 push (octave_function *f,
00219 symbol_table::scope_id scope = symbol_table::current_scope (),
00220 symbol_table::context_id context = symbol_table::current_context ())
00221 {
00222 if (instance_ok ())
00223 instance->do_push (f, scope, context);
00224 }
00225
00226 static void
00227 push (symbol_table::scope_id scope = symbol_table::current_scope (),
00228 symbol_table::context_id context = symbol_table::current_context ())
00229 {
00230 if (instance_ok ())
00231 instance->do_push (0, scope, context);
00232 }
00233
00234 static void set_statement (tree_statement *s)
00235 {
00236 if (instance_ok ())
00237 instance->do_set_statement (s);
00238 }
00239
00240 static bool goto_frame (size_t n = 0, bool verbose = false)
00241 {
00242 return instance_ok () ? instance->do_goto_frame (n, verbose) : false;
00243 }
00244
00245 static void restore_frame (size_t n)
00246 {
00247 goto_frame (n);
00248 }
00249
00250 static bool goto_frame_relative (int n, bool verbose = false)
00251 {
00252 return instance_ok ()
00253 ? instance->do_goto_frame_relative (n, verbose) : false;
00254 }
00255
00256 static void goto_caller_frame (void)
00257 {
00258 if (instance_ok ())
00259 instance->do_goto_caller_frame ();
00260 }
00261
00262 static void goto_base_frame (void)
00263 {
00264 if (instance_ok ())
00265 instance->do_goto_base_frame ();
00266 }
00267
00268 static octave_map backtrace (size_t nskip, octave_idx_type& curr_user_frame)
00269 {
00270 return instance_ok ()
00271 ? instance->do_backtrace (nskip, curr_user_frame) : octave_map ();
00272 }
00273
00274 static octave_map empty_backtrace (void);
00275
00276 static void pop (void)
00277 {
00278 if (instance_ok ())
00279 instance->do_pop ();
00280 }
00281
00282 static void clear (void)
00283 {
00284 if (instance_ok ())
00285 instance->do_clear ();
00286 }
00287
00288 static void backtrace_error_message (void)
00289 {
00290 if (instance_ok ())
00291 instance->do_backtrace_error_message ();
00292 }
00293
00294 private:
00295
00296
00297 std::deque<call_stack_elt> cs;
00298
00299 size_t curr_frame;
00300
00301 static octave_call_stack *instance;
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 #endif