GNU Octave  4.0.0
A high-level interpreted language, primarily intended for numerical computations, mostly compatible with Matlab
 All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Properties Friends Macros Pages
toplev.h
Go to the documentation of this file.
1 /*
2 
3 Copyright (C) 1993-2015 John W. Eaton
4 
5 This file is part of Octave.
6 
7 Octave is free software; you can redistribute it and/or modify it
8 under the terms of the GNU General Public License as published by the
9 Free Software Foundation; either version 3 of the License, or (at your
10 option) any later version.
11 
12 Octave is distributed in the hope that it will be useful, but WITHOUT
13 ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
14 FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
15 for more details.
16 
17 You should have received a copy of the GNU General Public License
18 along with Octave; see the file COPYING. If not, see
19 <http://www.gnu.org/licenses/>.
20 
21 */
22 
23 #if !defined (octave_toplev_h)
24 #define octave_toplev_h 1
25 
26 #include <cstdio>
27 
28 #include <deque>
29 #include <string>
30 
31 class octave_value;
32 class octave_value_list;
33 class octave_function;
34 class octave_user_script;
35 class tree_statement;
37 class charMatrix;
38 
39 #include "quit.h"
40 
41 #include "input.h"
42 #include "oct-map.h"
43 #include "symtab.h"
44 
45 
46 typedef void (*octave_exit_func) (int);
48 
49 extern OCTINTERP_API bool quit_allowed;
50 
52 
53 extern OCTINTERP_API int exit_status;
54 
55 extern OCTINTERP_API void
56 clean_up_and_exit (int status, bool safe_to_return = false);
57 
58 extern OCTINTERP_API void recover_from_exception (void);
59 
60 extern OCTINTERP_API int main_loop (void);
61 
62 extern OCTINTERP_API void
63 octave_add_atexit_function (const std::string& fname);
64 
65 extern OCTINTERP_API bool
66 octave_remove_atexit_function (const std::string& fname);
67 
68 // TRUE means we are ready to interpret commands, but not everything
69 // is ready for interactive use.
71 
72 // TRUE means we've processed all the init code and we are good to go.
74 
75 class
78 {
79 protected:
80 
81  octave_call_stack (void) : cs (), curr_frame (0) { }
82 
83 public:
84 
86  {
87  public:
88 
89  friend class octave_call_stack;
90 
92  symbol_table::context_id context = 0, size_t prev = 0)
93  : m_fcn (fcn), m_line (-1), m_column (-1), m_scope (scope),
94  m_context (context), m_prev (prev)
95  { }
96 
97  stack_frame (const stack_frame& elt)
98  : m_fcn (elt.m_fcn), m_line (elt.m_line), m_column (elt.m_column),
99  m_scope (elt.m_scope), m_context (elt.m_context), m_prev (elt.m_prev)
100  { }
101 
102  int line (void) const { return m_line; }
103 
104  int column (void) const { return m_column; }
105 
106  std::string fcn_file_name (void) const;
107 
108  std::string fcn_name (bool print_subfn = true) const;
109 
110  private:
111 
113  int m_line;
114  int m_column;
117  size_t m_prev;
118  };
119 
120  typedef std::deque<stack_frame>::iterator iterator;
121  typedef std::deque<stack_frame>::const_iterator const_iterator;
122 
123  typedef std::deque<stack_frame>::reverse_iterator reverse_iterator;
124  typedef std::deque<stack_frame>::const_reverse_iterator const_reverse_iterator;
125 
126  static void create_instance (void);
127 
128  static bool instance_ok (void)
129  {
130  bool retval = true;
131 
132  if (! instance)
133  create_instance ();
134 
135  if (! instance)
136  {
137  ::error ("unable to create call stack object!");
138 
139  retval = false;
140  }
141 
142  return retval;
143  }
144 
145  // Current function (top of stack).
146  static octave_function *current (void)
147  {
148  return instance_ok () ? instance->do_current () : 0;
149  }
150 
151  // Current line in current function.
152  static int current_line (void)
153  {
154  return instance_ok () ? instance->do_current_line () : -1;
155  }
156 
157  // Current column in current function.
158  static int current_column (void)
159  {
160  return instance_ok () ? instance->do_current_column () : -1;
161  }
162 
163  // Line in user code caller.
164  static int caller_user_code_line (void)
165  {
166  return instance_ok () ? instance->do_caller_user_code_line () : -1;
167  }
168 
169  // Column in user code caller.
170  static int caller_user_code_column (void)
171  {
172  return instance_ok () ? instance->do_caller_user_code_column () : -1;
173  }
174 
175  // Caller function, may be built-in.
176  static octave_function *caller (void)
177  {
178  return instance_ok () ? instance->do_caller () : 0;
179  }
180 
181  static size_t current_frame (void)
182  {
183  return instance_ok () ? instance->do_current_frame () : 0;
184  }
185 
186  static size_t size (void)
187  {
188  return instance_ok () ? instance->do_size () : 0;
189  }
190 
191  static size_t num_user_code_frames (octave_idx_type& curr_user_frame)
192  {
193  return instance_ok ()
194  ? instance->do_num_user_code_frames (curr_user_frame) : 0;
195  }
196 
198  {
199  return instance_ok () ? instance->do_current_scope () : 0;
200  }
201 
203  {
204  return instance_ok () ? instance->do_current_context () : 0;
205  }
206 
207  /*
208  static stack_frame frame (size_t idx)
209  {
210  return instance_ok () ? instance->do_frame (idx) : stack_frame ();
211  }
212  */
213  // Function at location N on the call stack (N == 0 is current), may
214  // be built-in.
215  static octave_function *element (size_t n)
216  {
217  return instance_ok () ? instance->do_element (n) : 0;
218  }
219 
220  // First user-defined function on the stack.
221  static octave_user_code *caller_user_code (size_t nskip = 0)
222  {
223  return instance_ok () ? instance->do_caller_user_code (nskip) : 0;
224  }
225 
226  // Return TRUE if all elements on the call stack are scripts.
227  static bool all_scripts (void)
228  {
229  return instance_ok () ? instance->do_all_scripts () : false;
230  }
231 
232  static void
236  {
237  if (instance_ok ())
238  instance->do_push (f, scope, context);
239  }
240 
241  static void
244  {
245  if (instance_ok ())
246  instance->do_push (0, scope, context);
247  }
248 
249  static void set_location (int l, int c)
250  {
251  if (instance_ok ())
252  instance->do_set_location (l, c);
253  }
254 
255  static void set_line (int l)
256  {
257  if (instance_ok ())
258  instance->do_set_line (l);
259  }
260 
261  static void set_column (int c)
262  {
263  if (instance_ok ())
264  instance->do_set_column (c);
265  }
266 
267  static bool goto_frame (size_t n = 0, bool verbose = false)
268  {
269  return instance_ok () ? instance->do_goto_frame (n, verbose) : false;
270  }
271 
272  static void restore_frame (size_t n)
273  {
274  goto_frame (n);
275  }
276 
277  static bool goto_frame_relative (int n, bool verbose = false)
278  {
279  return instance_ok ()
280  ? instance->do_goto_frame_relative (n, verbose) : false;
281  }
282 
283  static void goto_caller_frame (void)
284  {
285  if (instance_ok ())
287  }
288 
289  static void goto_base_frame (void)
290  {
291  if (instance_ok ())
293  }
294 
295  static octave_map backtrace (size_t nskip = 0)
296  {
297  octave_idx_type curr_user_frame = -1;
298 
299  return instance_ok ()
300  ? instance->do_backtrace (nskip, curr_user_frame, true)
301  : octave_map ();
302  }
303 
304  static octave_map backtrace (size_t nskip, octave_idx_type& curr_user_frame,
305  bool print_subfn = true)
306  {
307  return instance_ok ()
308  ? instance->do_backtrace (nskip, curr_user_frame, print_subfn)
309  : octave_map ();
310  }
311 
312  static std::list<octave_call_stack::stack_frame>
313  backtrace_frames (size_t nskip = 0)
314  {
315  octave_idx_type curr_user_frame = -1;
316 
317  return instance_ok ()
318  ? instance->do_backtrace_frames (nskip, curr_user_frame)
319  : std::list<octave_call_stack::stack_frame> ();
320  }
321 
322  static std::list<octave_call_stack::stack_frame>
323  backtrace_frames (size_t nskip, octave_idx_type& curr_user_frame)
324  {
325  return instance_ok ()
326  ? instance->do_backtrace_frames (nskip, curr_user_frame)
327  : std::list<octave_call_stack::stack_frame> ();
328  }
329 
330  static octave_map empty_backtrace (void);
331 
332  static void pop (void)
333  {
334  if (instance_ok ())
335  instance->do_pop ();
336  }
337 
338  static void clear (void)
339  {
340  if (instance_ok ())
341  instance->do_clear ();
342  }
343 
344 private:
345 
346  // The current call stack.
347  std::deque<stack_frame> cs;
348 
349  size_t curr_frame;
350 
352 
353  static void cleanup_instance (void) { delete instance; instance = 0; }
354 
355  int do_current_line (void) const;
356 
357  int do_current_column (void) const;
358 
359  int do_caller_user_code_line (void) const;
360 
361  int do_caller_user_code_column (void) const;
362 
364  {
365  return curr_frame > 1 ? cs[curr_frame-1].m_fcn : cs[0].m_fcn;
366  }
367 
368  size_t do_current_frame (void) { return curr_frame; }
369 
370  size_t do_size (void) { return cs.size (); }
371 
372  size_t do_num_user_code_frames (octave_idx_type& curr_user_frame) const;
373 
375  {
376  return curr_frame > 0 && curr_frame < cs.size ()
377  ? cs[curr_frame].m_scope : 0;
378  }
379 
381  {
382  return curr_frame > 0 && curr_frame < cs.size ()
383  ? cs[curr_frame].m_context : 0;
384  }
385 
386  /* const stack_frame& do_frame (size_t idx)
387  {
388  static stack_frame foobar;
389 
390  return idx < cs.size () ? cs[idx] : foobar;
391  }
392  */
394  {
395  octave_function *retval = 0;
396 
397  if (cs.size () > n)
398  {
399  stack_frame& elt = cs[n];
400  retval = elt.m_fcn;
401  }
402 
403  return retval;
404  }
405 
406  octave_user_code *do_caller_user_code (size_t nskip) const;
407 
408  bool do_all_scripts (void) const;
409 
412  {
413  size_t prev_frame = curr_frame;
414  curr_frame = cs.size ();
415  cs.push_back (stack_frame (fcn, scope, context, prev_frame));
416  symbol_table::set_scope_and_context (scope, context);
417  }
418 
420  {
421  octave_function *retval = 0;
422 
423  if (! cs.empty ())
424  {
425  const stack_frame& elt = cs[curr_frame];
426  retval = elt.m_fcn;
427  }
428 
429  return retval;
430  }
431 
432  void do_set_location (int l, int c)
433  {
434  if (! cs.empty ())
435  {
436  stack_frame& elt = cs.back ();
437 
438  elt.m_line = l;
439  elt.m_column = c;
440  }
441  }
442 
443  void do_set_line (int l)
444  {
445  if (! cs.empty ())
446  {
447  stack_frame& elt = cs.back ();
448 
449  elt.m_line = l;
450  }
451  }
452 
453  void do_set_column (int c)
454  {
455  if (! cs.empty ())
456  {
457  stack_frame& elt = cs.back ();
458 
459  elt.m_column = c;
460  }
461  }
462 
463  std::list<octave_call_stack::stack_frame>
464  do_backtrace_frames (size_t nskip, octave_idx_type& curr_user_frame) const;
465 
466  octave_map do_backtrace (size_t nskip,
467  octave_idx_type& curr_user_frame,
468  bool print_subfn) const;
469 
470  bool do_goto_frame (size_t n, bool verbose);
471 
472  bool do_goto_frame_relative (int n, bool verbose);
473 
474  void do_goto_caller_frame (void);
475 
476  void do_goto_base_frame (void);
477 
478  void do_pop (void)
479  {
480  if (cs.size () > 1)
481  {
482  const stack_frame& elt = cs.back ();
483  curr_frame = elt.m_prev;
484  cs.pop_back ();
485  const stack_frame& new_elt = cs[curr_frame];
487  }
488  }
489 
490  void do_clear (void) { cs.clear (); }
491 };
492 
493 // Call a function with exceptions handled to avoid problems with
494 // errors while shutting down.
495 
496 #define OCTAVE_IGNORE_EXCEPTION(E) \
497  catch (E) \
498  { \
499  std::cerr << "error: ignoring " #E " while preparing to exit" << std::endl; \
500  recover_from_exception (); \
501  }
502 
503 #define OCTAVE_SAFE_CALL(F, ARGS) \
504  do \
505  { \
506  try \
507  { \
508  unwind_protect frame; \
509  \
510  frame.protect_var (Vdebug_on_error); \
511  frame.protect_var (Vdebug_on_warning); \
512  \
513  Vdebug_on_error = false; \
514  Vdebug_on_warning = false; \
515  \
516  F ARGS; \
517  } \
518  OCTAVE_IGNORE_EXCEPTION (octave_interrupt_exception) \
519  OCTAVE_IGNORE_EXCEPTION (octave_execution_exception) \
520  OCTAVE_IGNORE_EXCEPTION (std::bad_alloc) \
521  \
522  if (error_state) \
523  error_state = 0; \
524  } \
525  while (0)
526 
527 #endif
static bool instance_ok(void)
Definition: toplev.h:128
static void restore_frame(size_t n)
Definition: toplev.h:272
size_t do_current_frame(void)
Definition: toplev.h:368
int line(void) const
Definition: toplev.h:102
std::string fcn_name(bool print_subfn=true) const
Definition: toplev.cc:114
void do_set_location(int l, int c)
Definition: toplev.h:432
size_t curr_frame
Definition: toplev.h:349
OCTINTERP_API bool octave_initialized
Definition: toplev.cc:103
static size_t num_user_code_frames(octave_idx_type &curr_user_frame)
Definition: toplev.h:191
void do_push(octave_function *fcn, symbol_table::scope_id scope, symbol_table::context_id context)
Definition: toplev.h:410
OCTINTERP_API bool octave_remove_atexit_function(const std::string &fname)
Definition: toplev.cc:1153
static void push(symbol_table::scope_id scope=symbol_table::current_scope(), symbol_table::context_id context=symbol_table::current_context())
Definition: toplev.h:242
static size_t size(void)
Definition: toplev.h:186
static bool all_scripts(void)
Definition: toplev.h:227
OCTINTERP_API octave_exit_func octave_exit
Definition: toplev.cc:88
int do_caller_user_code_column(void) const
Definition: toplev.cc:201
std::list< octave_call_stack::stack_frame > do_backtrace_frames(size_t nskip, octave_idx_type &curr_user_frame) const
Definition: toplev.cc:329
void error(const char *fmt,...)
Definition: error.cc:476
static octave_function * current(void)
Definition: toplev.h:146
bool do_all_scripts(void) const
Definition: toplev.cc:293
static bool goto_frame(size_t n=0, bool verbose=false)
Definition: toplev.h:267
std::deque< stack_frame >::iterator iterator
Definition: toplev.h:120
octave_function * do_current(void) const
Definition: toplev.h:419
static void set_location(int l, int c)
Definition: toplev.h:249
std::deque< stack_frame >::reverse_iterator reverse_iterator
Definition: toplev.h:123
static void goto_caller_frame(void)
Definition: toplev.h:283
void do_set_column(int c)
Definition: toplev.h:453
static void create_instance(void)
Definition: toplev.cc:134
OCTINTERP_API int exit_status
Definition: toplev.cc:96
void(* octave_exit_func)(int)
Definition: toplev.h:46
static context_id current_context(void)
Definition: symtab.h:1165
octave_function * do_caller(void) const
Definition: toplev.h:363
static int current_line(void)
Definition: toplev.h:152
std::deque< stack_frame > cs
Definition: toplev.h:347
symbol_table::scope_id do_current_scope(void) const
Definition: toplev.h:374
static octave_user_code * caller_user_code(size_t nskip=0)
Definition: toplev.h:221
static std::string fcn_file_name(const octave_value &fcn)
Definition: symtab.cc:1163
void do_goto_caller_frame(void)
Definition: toplev.cc:496
static std::list< octave_call_stack::stack_frame > backtrace_frames(size_t nskip, octave_idx_type &curr_user_frame)
Definition: toplev.h:323
static octave_function * caller(void)
Definition: toplev.h:176
OCTINTERP_API bool quit_allowed
Definition: toplev.cc:91
F77_RET_T const double const double * f
#define OCTINTERP_API
Definition: mexproto.h:66
static symbol_table::scope_id current_scope(void)
Definition: toplev.h:197
static size_t current_frame(void)
Definition: toplev.h:181
std::deque< stack_frame >::const_iterator const_iterator
Definition: toplev.h:121
void do_set_line(int l)
Definition: toplev.h:443
static llvm::LLVMContext & context
Definition: jit-typeinfo.cc:76
int do_current_column(void) const
Definition: toplev.cc:161
bool do_goto_frame(size_t n, bool verbose)
Definition: toplev.cc:402
octave_function * do_element(size_t n)
Definition: toplev.h:393
int do_caller_user_code_line(void) const
Definition: toplev.cc:175
OCTINTERP_API int main_loop(void)
Definition: toplev.cc:559
OCTINTERP_API void recover_from_exception(void)
Definition: toplev.cc:547
static void clear(void)
Definition: toplev.h:338
stack_frame(octave_function *fcn=0, symbol_table::scope_id scope=0, symbol_table::context_id context=0, size_t prev=0)
Definition: toplev.h:91
static void push(octave_function *f, symbol_table::scope_id scope=symbol_table::current_scope(), symbol_table::context_id context=symbol_table::current_context())
Definition: toplev.h:233
static void goto_base_frame(void)
Definition: toplev.h:289
symbol_table::context_id do_current_context(void) const
Definition: toplev.h:380
octave_map do_backtrace(size_t nskip, octave_idx_type &curr_user_frame, bool print_subfn) const
Definition: toplev.cc:363
static void set_column(int c)
Definition: toplev.h:261
symbol_table::scope_id m_scope
Definition: toplev.h:115
octave_call_stack(void)
Definition: toplev.h:81
size_t do_num_user_code_frames(octave_idx_type &curr_user_frame) const
Definition: toplev.cc:228
static int caller_user_code_line(void)
Definition: toplev.h:164
bool do_goto_frame_relative(int n, bool verbose)
Definition: toplev.cc:428
OCTINTERP_API void clean_up_and_exit(int status, bool safe_to_return=false)
Definition: toplev.cc:760
int column(void) const
Definition: toplev.h:104
OCTINTERP_API void octave_add_atexit_function(const std::string &fname)
Definition: toplev.cc:1147
OCTINTERP_API bool quitting_gracefully
Definition: toplev.cc:94
static symbol_table::context_id current_context(void)
Definition: toplev.h:202
static int current_column(void)
Definition: toplev.h:158
static octave_function * element(size_t n)
Definition: toplev.h:215
static int caller_user_code_column(void)
Definition: toplev.h:170
static std::list< octave_call_stack::stack_frame > backtrace_frames(size_t nskip=0)
Definition: toplev.h:313
void do_clear(void)
Definition: toplev.h:490
size_t do_size(void)
Definition: toplev.h:370
static void set_line(int l)
Definition: toplev.h:255
static void pop(void)
Definition: toplev.h:332
static octave_map empty_backtrace(void)
Definition: toplev.cc:323
static octave_call_stack * instance
Definition: toplev.h:351
static octave_map backtrace(size_t nskip, octave_idx_type &curr_user_frame, bool print_subfn=true)
Definition: toplev.h:304
void do_pop(void)
Definition: toplev.h:478
int do_current_line(void) const
Definition: toplev.cc:147
static bool goto_frame_relative(int n, bool verbose=false)
Definition: toplev.h:277
octave_user_code * do_caller_user_code(size_t nskip) const
Definition: toplev.cc:265
OCTINTERP_API bool octave_interpreter_ready
Definition: toplev.cc:100
stack_frame(const stack_frame &elt)
Definition: toplev.h:97
std::deque< stack_frame >::const_reverse_iterator const_reverse_iterator
Definition: toplev.h:124
static void cleanup_instance(void)
Definition: toplev.h:353
symbol_table::context_id m_context
Definition: toplev.h:116
static void set_scope_and_context(scope_id scope, context_id context)
Definition: symtab.h:1192
octave_function * m_fcn
Definition: toplev.h:112
void do_goto_base_frame(void)
Definition: toplev.cc:534
static scope_id current_scope(void)
Definition: symtab.h:1163
static octave_map backtrace(size_t nskip=0)
Definition: toplev.h:295