00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019
00020
00021
00022
00023
00024 #if !defined (octave_toplev_h)
00025 #define octave_toplev_h 1
00026
00027 #include <cstdio>
00028
00029 #include <deque>
00030 #include <string>
00031
00032 class octave_value;
00033 class octave_value_list;
00034 class octave_function;
00035 class octave_user_script;
00036 class tree_statement;
00037 class tree_statement_list;
00038 class charMatrix;
00039
00040 #include "quit.h"
00041
00042 #include "input.h"
00043 #include "oct-map.h"
00044
00045
00046 typedef void (*octave_exit_func) (int);
00047 extern OCTINTERP_API octave_exit_func octave_exit;
00048
00049 extern OCTINTERP_API bool quit_allowed;
00050
00051 extern OCTINTERP_API bool quitting_gracefully;
00052
00053 extern OCTINTERP_API int exit_status;
00054
00055 extern OCTINTERP_API void
00056 clean_up_and_exit (int);
00057
00058 extern OCTINTERP_API void recover_from_exception (void);
00059
00060 extern OCTINTERP_API int main_loop (void);
00061
00062 extern OCTINTERP_API void
00063 do_octave_atexit (void);
00064
00065 extern OCTINTERP_API void
00066 octave_add_atexit_function (const std::string& fname);
00067
00068 extern OCTINTERP_API bool
00069 octave_remove_atexit_function (const std::string& fname);
00070
00071
00072 extern OCTINTERP_API tree_statement_list *global_command;
00073
00074
00075
00076 extern OCTINTERP_API bool octave_interpreter_ready;
00077
00078
00079 extern OCTINTERP_API bool octave_initialized;
00080
00081 class
00082 OCTINTERP_API
00083 octave_call_stack
00084 {
00085 private:
00086
00087 struct call_stack_elt
00088 {
00089 call_stack_elt (octave_function *f, symbol_table::scope_id s,
00090 symbol_table::context_id c, size_t p = 0)
00091 : fcn (f), stmt (0), scope (s), context (c), prev (p) { }
00092
00093 call_stack_elt (const call_stack_elt& elt)
00094 : fcn (elt.fcn), stmt (elt.stmt), scope (elt.scope),
00095 context (elt.context), prev (elt.prev) { }
00096
00097 octave_function *fcn;
00098 tree_statement *stmt;
00099 symbol_table::scope_id scope;
00100 symbol_table::context_id context;
00101 size_t prev;
00102 };
00103
00104 protected:
00105
00106 octave_call_stack (void) : cs (), curr_frame (0) { }
00107
00108 public:
00109
00110 typedef std::deque<call_stack_elt>::iterator iterator;
00111 typedef std::deque<call_stack_elt>::const_iterator const_iterator;
00112
00113 typedef std::deque<call_stack_elt>::reverse_iterator reverse_iterator;
00114 typedef std::deque<call_stack_elt>::const_reverse_iterator const_reverse_iterator;
00115
00116 static bool instance_ok (void)
00117 {
00118 bool retval = true;
00119
00120 if (! instance)
00121 {
00122 instance = new octave_call_stack ();
00123
00124 if (instance)
00125 instance->do_push (0, symbol_table::top_scope (), 0);
00126 else
00127 {
00128 ::error ("unable to create call stack object!");
00129
00130 retval = false;
00131 }
00132 }
00133
00134 return retval;
00135 }
00136
00137
00138 static octave_function *current (void)
00139 {
00140 return instance_ok () ? instance->do_current () : 0;
00141 }
00142
00143
00144 static tree_statement *current_statement (void)
00145 {
00146 return instance_ok () ? instance->do_current_statement () : 0;
00147 }
00148
00149
00150 static int current_line (void)
00151 {
00152 return instance_ok () ? instance->do_current_line () : -1;
00153 }
00154
00155
00156 static int current_column (void)
00157 {
00158 return instance_ok () ? instance->do_current_column () : -1;
00159 }
00160
00161
00162 static int caller_user_code_line (void)
00163 {
00164 return instance_ok () ? instance->do_caller_user_code_line () : -1;
00165 }
00166
00167
00168 static int caller_user_code_column (void)
00169 {
00170 return instance_ok () ? instance->do_caller_user_code_column () : -1;
00171 }
00172
00173
00174 static octave_function *caller (void)
00175 {
00176 return instance_ok () ? instance->do_caller () : 0;
00177 }
00178
00179 static size_t current_frame (void)
00180 {
00181 return instance_ok () ? instance->do_current_frame () : 0;
00182 }
00183
00184 static size_t size (void)
00185 {
00186 return instance_ok () ? instance->do_size () : 0;
00187 }
00188
00189 static size_t num_user_code_frames (octave_idx_type& curr_user_frame)
00190 {
00191 return instance_ok ()
00192 ? instance->do_num_user_code_frames (curr_user_frame) : 0;
00193 }
00194
00195 static symbol_table::scope_id current_scope (void)
00196 {
00197 return instance_ok () ? instance->do_current_scope () : 0;
00198 }
00199
00200 static symbol_table::context_id current_context (void)
00201 {
00202 return instance_ok () ? instance->do_current_context () : 0;
00203 }
00204
00205
00206
00207 static octave_function *element (size_t n)
00208 {
00209 return instance_ok () ? instance->do_element (n) : 0;
00210 }
00211
00212
00213 static octave_user_code *caller_user_code (size_t nskip = 0)
00214 {
00215 return instance_ok () ? instance->do_caller_user_code (nskip) : 0;
00216 }
00217
00218 static void
00219 push (octave_function *f,
00220 symbol_table::scope_id scope = symbol_table::current_scope (),
00221 symbol_table::context_id context = symbol_table::current_context ())
00222 {
00223 if (instance_ok ())
00224 instance->do_push (f, scope, context);
00225 }
00226
00227 static void
00228 push (symbol_table::scope_id scope = symbol_table::current_scope (),
00229 symbol_table::context_id context = symbol_table::current_context ())
00230 {
00231 if (instance_ok ())
00232 instance->do_push (0, scope, context);
00233 }
00234
00235 static void set_statement (tree_statement *s)
00236 {
00237 if (instance_ok ())
00238 instance->do_set_statement (s);
00239 }
00240
00241 static bool goto_frame (size_t n = 0, bool verbose = false)
00242 {
00243 return instance_ok () ? instance->do_goto_frame (n, verbose) : false;
00244 }
00245
00246 static void restore_frame (size_t n)
00247 {
00248 goto_frame (n);
00249 }
00250
00251 static bool goto_frame_relative (int n, bool verbose = false)
00252 {
00253 return instance_ok ()
00254 ? instance->do_goto_frame_relative (n, verbose) : false;
00255 }
00256
00257 static void goto_caller_frame (void)
00258 {
00259 if (instance_ok ())
00260 instance->do_goto_caller_frame ();
00261 }
00262
00263 static void goto_base_frame (void)
00264 {
00265 if (instance_ok ())
00266 instance->do_goto_base_frame ();
00267 }
00268
00269 static Octave_map backtrace (size_t nskip, octave_idx_type& curr_user_frame)
00270 {
00271 return instance_ok ()
00272 ? instance->do_backtrace (nskip, curr_user_frame) : Octave_map ();
00273 }
00274
00275 static void pop (void)
00276 {
00277 if (instance_ok ())
00278 instance->do_pop ();
00279 }
00280
00281 static void clear (void)
00282 {
00283 if (instance_ok ())
00284 instance->do_clear ();
00285 }
00286
00287 static void backtrace_error_message (void)
00288 {
00289 if (instance_ok ())
00290 instance->do_backtrace_error_message ();
00291 }
00292
00293 private:
00294
00295
00296 std::deque<call_stack_elt> cs;
00297
00298 size_t curr_frame;
00299
00300 static octave_call_stack *instance;
00301
00302 int do_current_line (void) const;
00303
00304 int do_current_column (void) const;
00305
00306 int do_caller_user_code_line (void) const;
00307
00308 int do_caller_user_code_column (void) const;
00309
00310 octave_function *do_caller (void) const
00311 {
00312 return curr_frame > 1 ? cs[curr_frame-1].fcn : cs[0].fcn;
00313 }
00314
00315 size_t do_current_frame (void) { return curr_frame; }
00316
00317 size_t do_size (void) { return cs.size (); }
00318
00319 size_t do_num_user_code_frames (octave_idx_type& curr_user_frame) const;
00320
00321 symbol_table::scope_id do_current_scope (void) const
00322 {
00323 return curr_frame > 0 && curr_frame < cs.size ()
00324 ? cs[curr_frame].scope : 0;
00325 }
00326
00327 symbol_table::context_id do_current_context (void) const
00328 {
00329 return curr_frame > 0 && curr_frame < cs.size ()
00330 ? cs[curr_frame].context : 0;
00331 }
00332
00333 octave_function *do_element (size_t n)
00334 {
00335 octave_function *retval = 0;
00336
00337 if (cs.size () > n)
00338 {
00339 call_stack_elt& elt = cs[n];
00340 retval = elt.fcn;
00341 }
00342
00343 return retval;
00344 }
00345
00346 octave_user_code *do_caller_user_code (size_t nskip) const;
00347
00348 void do_push (octave_function *f, symbol_table::scope_id scope,
00349 symbol_table::context_id context)
00350 {
00351 size_t prev_frame = curr_frame;
00352 curr_frame = cs.size ();
00353 cs.push_back (call_stack_elt (f, scope, context, prev_frame));
00354 symbol_table::set_scope_and_context (scope, context);
00355 }
00356
00357 octave_function *do_current (void) const
00358 {
00359 octave_function *retval = 0;
00360
00361 if (! cs.empty ())
00362 {
00363 const call_stack_elt& elt = cs[curr_frame];
00364 retval = elt.fcn;
00365 }
00366
00367 return retval;
00368 }
00369
00370 tree_statement *do_current_statement (void) const
00371 {
00372 tree_statement *retval = 0;
00373
00374 if (! cs.empty ())
00375 {
00376 const call_stack_elt& elt = cs[curr_frame];
00377 retval = elt.stmt;
00378 }
00379
00380 return retval;
00381 }
00382
00383 void do_set_statement (tree_statement *s)
00384 {
00385 if (! cs.empty ())
00386 {
00387 call_stack_elt& elt = cs.back ();
00388 elt.stmt = s;
00389 }
00390 }
00391
00392 Octave_map do_backtrace (size_t nskip,
00393 octave_idx_type& curr_user_frame) const;
00394
00395 bool do_goto_frame (size_t n, bool verbose);
00396
00397 bool do_goto_frame_relative (int n, bool verbose);
00398
00399 void do_goto_caller_frame (void);
00400
00401 void do_goto_base_frame (void);
00402
00403 void do_pop (void)
00404 {
00405 if (cs.size () > 1)
00406 {
00407 const call_stack_elt& elt = cs.back ();
00408 curr_frame = elt.prev;
00409 cs.pop_back ();
00410 const call_stack_elt& new_elt = cs[curr_frame];
00411 symbol_table::set_scope_and_context (new_elt.scope, new_elt.context);
00412 }
00413 }
00414
00415 void do_clear (void) { cs.clear (); }
00416
00417 void do_backtrace_error_message (void) const;
00418 };
00419
00420 #endif
00421
00422
00423
00424
00425
00426