GNU Octave  4.2.1
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
call-stack.h
Go to the documentation of this file.
1 /*
2 
3 Copyright (C) 1993-2017 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_call_stack_h)
24 #define octave_call_stack_h 1
25 
26 #include "octave-config.h"
27 
28 #include <deque>
29 #include <string>
30 
31 class octave_function;
32 class octave_user_code;
33 class octave_user_script;
34 
35 #include "input.h"
36 #include "oct-map.h"
37 #include "symtab.h"
38 
39 class
42 {
43 protected:
44 
45  octave_call_stack (void) : cs (), curr_frame (0) { }
46 
47 public:
48 
50  {
51  public:
52 
53  friend class octave_call_stack;
54 
56  symbol_table::context_id context = 0, size_t prev = 0)
57  : m_fcn (fcn), m_line (-1), m_column (-1), m_scope (scope),
58  m_context (context), m_prev (prev)
59  { }
60 
61  stack_frame (const stack_frame& elt)
62  : m_fcn (elt.m_fcn), m_line (elt.m_line), m_column (elt.m_column),
63  m_scope (elt.m_scope), m_context (elt.m_context), m_prev (elt.m_prev)
64  { }
65 
66  int line (void) const { return m_line; }
67 
68  int column (void) const { return m_column; }
69 
70  std::string fcn_file_name (void) const;
71 
72  std::string fcn_name (bool print_subfn = true) const;
73 
74  bool operator == (const stack_frame &rhs) const;
75 
76  private:
77 
79  int m_line;
80  int m_column;
83  size_t m_prev;
84  };
85 
86  typedef std::deque<stack_frame>::iterator iterator;
87  typedef std::deque<stack_frame>::const_iterator const_iterator;
88 
89  typedef std::deque<stack_frame>::reverse_iterator reverse_iterator;
90  typedef std::deque<stack_frame>::const_reverse_iterator const_reverse_iterator;
91 
92  static void create_instance (void);
93 
94  static bool instance_ok (void)
95  {
96  bool retval = true;
97 
98  if (! instance)
99  create_instance ();
100 
101  if (! instance)
102  error ("unable to create call stack object!");
103 
104  return retval;
105  }
106 
107  // Current function (top of stack).
108  static octave_function *current (void)
109  {
110  return instance_ok () ? instance->do_current () : 0;
111  }
112 
113  // Current line in current function.
114  static int current_line (void)
115  {
116  return instance_ok () ? instance->do_current_line () : -1;
117  }
118 
119  // Current column in current function.
120  static int current_column (void)
121  {
122  return instance_ok () ? instance->do_current_column () : -1;
123  }
124 
125  // Caller function, may be built-in.
126  static octave_function *caller (void)
127  {
128  return instance_ok () ? instance->do_caller () : 0;
129  }
130 
131  static size_t current_frame (void)
132  {
133  return instance_ok () ? instance->do_current_frame () : 0;
134  }
135 
136  static size_t size (void)
137  {
138  return instance_ok () ? instance->do_size () : 0;
139  }
140 
141  static size_t num_user_code_frames (octave_idx_type& curr_user_frame)
142  {
143  return instance_ok ()
144  ? instance->do_num_user_code_frames (curr_user_frame) : 0;
145  }
146 
148  {
149  return instance_ok () ? instance->do_current_scope () : 0;
150  }
151 
153  {
154  return instance_ok () ? instance->do_current_context () : 0;
155  }
156 
157 #if 0
158  static stack_frame frame (size_t idx)
159  {
160  return instance_ok () ? instance->do_frame (idx) : stack_frame ();
161  }
162 #endif
163 
164  // Function at location N on the call stack (N == 0 is current), may
165  // be built-in.
166  static octave_function *element (size_t n)
167  {
168  return instance_ok () ? instance->do_element (n) : 0;
169  }
170 
171  // User code caller.
172  static octave_user_code *caller_user_code (size_t nskip = 0)
173  {
174  return instance_ok () ? instance->do_caller_user_code (nskip) : 0;
175  }
176 
177  // Line in user code caller.
178  static int caller_user_code_line (void)
179  {
180  return instance_ok () ? instance->do_caller_user_code_line () : -1;
181  }
182 
183  // Column in user code caller.
184  static int caller_user_code_column (void)
185  {
186  return instance_ok () ? instance->do_caller_user_code_column () : -1;
187  }
188 
189  // Current function that we are debugging.
191  {
192  return instance_ok () ? instance->do_debug_user_code () : 0;
193  }
194 
195  // Line number in current function that we are debugging.
196  static int debug_user_code_line (void)
197  {
198  return instance_ok () ? instance->do_debug_user_code_line () : 0;
199  }
200 
201  // Column number in current function that we are debugging.
202  static int debug_user_code_column (void)
203  {
204  return instance_ok () ? instance->do_debug_user_code_column () : 0;
205  }
206 
207  // Return TRUE if all elements on the call stack are scripts.
208  static bool all_scripts (void)
209  {
210  return instance_ok () ? instance->do_all_scripts () : false;
211  }
212 
213  static void
217  {
218  if (instance_ok ())
219  instance->do_push (f, scope, context);
220  }
221 
222  static void
225  {
226  if (instance_ok ())
227  instance->do_push (0, scope, context);
228  }
229 
230  static void set_location (int l, int c)
231  {
232  if (instance_ok ())
233  instance->do_set_location (l, c);
234  }
235 
236  static void set_line (int l)
237  {
238  if (instance_ok ())
239  instance->do_set_line (l);
240  }
241 
242  static void set_column (int c)
243  {
244  if (instance_ok ())
245  instance->do_set_column (c);
246  }
247 
248  static bool goto_frame (size_t n = 0, bool verbose = false)
249  {
250  return instance_ok () ? instance->do_goto_frame (n, verbose) : false;
251  }
252 
253  static void restore_frame (size_t n)
254  {
255  goto_frame (n);
256  }
257 
258  static bool goto_frame_relative (int n, bool verbose = false)
259  {
260  return instance_ok ()
261  ? instance->do_goto_frame_relative (n, verbose) : false;
262  }
263 
264  static void goto_caller_frame (void)
265  {
266  if (instance_ok ())
268  }
269 
270  static void goto_base_frame (void)
271  {
272  if (instance_ok ())
274  }
275 
276  static octave_map backtrace (size_t nskip = 0)
277  {
278  octave_idx_type curr_user_frame = -1;
279 
280  return instance_ok ()
281  ? instance->do_backtrace (nskip, curr_user_frame, true)
282  : octave_map ();
283  }
284 
285  static octave_map backtrace (size_t nskip, octave_idx_type& curr_user_frame,
286  bool print_subfn = true)
287  {
288  return instance_ok ()
289  ? instance->do_backtrace (nskip, curr_user_frame, print_subfn)
290  : octave_map ();
291  }
292 
293  static std::list<octave_call_stack::stack_frame>
294  backtrace_frames (size_t nskip = 0)
295  {
296  octave_idx_type curr_user_frame = -1;
297 
298  return instance_ok ()
299  ? instance->do_backtrace_frames (nskip, curr_user_frame)
300  : std::list<octave_call_stack::stack_frame> ();
301  }
302 
303  static std::list<octave_call_stack::stack_frame>
304  backtrace_frames (size_t nskip, octave_idx_type& curr_user_frame)
305  {
306  return instance_ok ()
307  ? instance->do_backtrace_frames (nskip, curr_user_frame)
308  : std::list<octave_call_stack::stack_frame> ();
309  }
310 
311  static octave_map empty_backtrace (void);
312 
313  static void pop (void)
314  {
315  if (instance_ok ())
316  instance->do_pop ();
317  }
318 
319  static void clear (void)
320  {
321  if (instance_ok ())
322  instance->do_clear ();
323  }
324 
325 private:
326 
327  // The current call stack.
328  std::deque<stack_frame> cs;
329 
330  size_t curr_frame;
331 
333 
334  static void cleanup_instance (void) { delete instance; instance = 0; }
335 
336  int do_current_line (void) const;
337 
338  int do_current_column (void) const;
339 
341  {
342  return curr_frame > 1 ? cs[curr_frame-1].m_fcn : cs[0].m_fcn;
343  }
344 
345  size_t do_current_frame (void) { return curr_frame; }
346 
347  size_t do_size (void) { return cs.size (); }
348 
349  size_t do_num_user_code_frames (octave_idx_type& curr_user_frame) const;
350 
352  {
353  return curr_frame > 0 && curr_frame < cs.size ()
354  ? cs[curr_frame].m_scope : 0;
355  }
356 
358  {
359  return curr_frame > 0 && curr_frame < cs.size ()
360  ? cs[curr_frame].m_context : 0;
361  }
362 
363 #if 0
364  const stack_frame& do_frame (size_t idx)
365  {
366  static stack_frame foobar;
367 
368  return idx < cs.size () ? cs[idx] : foobar;
369  }
370 #endif
371 
373  {
374  octave_function *retval = 0;
375 
376  if (cs.size () > n)
377  {
378  stack_frame& elt = cs[n];
379  retval = elt.m_fcn;
380  }
381 
382  return retval;
383  }
384 
385  octave_user_code *do_caller_user_code (size_t nskip) const;
386  int do_caller_user_code_line (void) const;
387  int do_caller_user_code_column (void) const;
388 
389  octave_user_code *do_debug_user_code (void) const;
390  int do_debug_user_code_line (void) const;
391  int do_debug_user_code_column (void) const;
392 
393  bool do_all_scripts (void) const;
394 
397  {
398  size_t prev_frame = curr_frame;
399  curr_frame = cs.size ();
400  cs.push_back (stack_frame (fcn, scope, context, prev_frame));
401  symbol_table::set_scope_and_context (scope, context);
402  }
403 
405  {
406  octave_function *retval = 0;
407 
408  if (! cs.empty ())
409  {
410  const stack_frame& elt = cs[curr_frame];
411  retval = elt.m_fcn;
412  }
413 
414  return retval;
415  }
416 
417  void do_set_location (int l, int c)
418  {
419  if (! cs.empty ())
420  {
421  stack_frame& elt = cs.back ();
422 
423  elt.m_line = l;
424  elt.m_column = c;
425  }
426  }
427 
428  void do_set_line (int l)
429  {
430  if (! cs.empty ())
431  {
432  stack_frame& elt = cs.back ();
433 
434  elt.m_line = l;
435  }
436  }
437 
438  void do_set_column (int c)
439  {
440  if (! cs.empty ())
441  {
442  stack_frame& elt = cs.back ();
443 
444  elt.m_column = c;
445  }
446  }
447 
448  std::list<octave_call_stack::stack_frame>
449  do_backtrace_frames (size_t nskip, octave_idx_type& curr_user_frame) const;
450 
451  octave_map do_backtrace (size_t nskip,
452  octave_idx_type& curr_user_frame,
453  bool print_subfn) const;
454 
455  bool do_goto_frame (size_t n, bool verbose);
456 
457  bool do_goto_frame_relative (int n, bool verbose);
458 
459  void do_goto_caller_frame (void);
460 
461  void do_goto_base_frame (void);
462 
463  void do_pop (void)
464  {
465  if (cs.size () > 1)
466  {
467  const stack_frame& elt = cs.back ();
468  curr_frame = elt.m_prev;
469  cs.pop_back ();
470  const stack_frame& new_elt = cs[curr_frame];
472  }
473  }
474 
475  void do_clear (void) { cs.clear (); }
476 };
477 
478 #endif
static bool instance_ok(void)
Definition: call-stack.h:94
static void restore_frame(size_t n)
Definition: call-stack.h:253
size_t do_current_frame(void)
Definition: call-stack.h:345
std::string fcn_name(bool print_subfn=true) const
Definition: call-stack.cc:45
void do_set_location(int l, int c)
Definition: call-stack.h:417
static size_t num_user_code_frames(octave_idx_type &curr_user_frame)
Definition: call-stack.h:141
void do_push(octave_function *fcn, symbol_table::scope_id scope, symbol_table::context_id context)
Definition: call-stack.h:395
static void push(symbol_table::scope_id scope=symbol_table::current_scope(), symbol_table::context_id context=symbol_table::current_context())
Definition: call-stack.h:223
static size_t size(void)
Definition: call-stack.h:136
static bool all_scripts(void)
Definition: call-stack.h:208
F77_RET_T F77_REAL &F77_RET_T F77_DBLE &F77_RET_T F77_REAL &F77_RET_T F77_DBLE &F77_RET_T F77_REAL &F77_RET_T F77_DBLE &F77_RET_T const F77_REAL const F77_REAL F77_REAL &F77_RET_T const F77_DBLE const F77_DBLE F77_DBLE &F77_RET_T F77_REAL &F77_RET_T F77_DBLE &F77_RET_T F77_DBLE &F77_RET_T F77_REAL &F77_RET_T F77_REAL &F77_RET_T F77_DBLE &F77_RET_T const F77_DBLE F77_DBLE &F77_RET_T const F77_REAL F77_REAL &F77_RET_T F77_REAL F77_REAL &F77_RET_T F77_DBLE F77_DBLE &F77_RET_T const F77_DBLE const F77_DBLE * f
int do_caller_user_code_column(void) const
Definition: call-stack.cc:216
std::list< octave_call_stack::stack_frame > do_backtrace_frames(size_t nskip, octave_idx_type &curr_user_frame) const
Definition: call-stack.cc:368
void error(const char *fmt,...)
Definition: error.cc:570
static octave_function * current(void)
Definition: call-stack.h:108
bool do_all_scripts(void) const
Definition: call-stack.cc:332
static bool goto_frame(size_t n=0, bool verbose=false)
Definition: call-stack.h:248
std::deque< stack_frame >::iterator iterator
Definition: call-stack.h:86
octave_function * do_current(void) const
Definition: call-stack.h:404
static void set_location(int l, int c)
Definition: call-stack.h:230
int do_debug_user_code_line(void) const
Definition: call-stack.cc:270
std::deque< stack_frame >::reverse_iterator reverse_iterator
Definition: call-stack.h:89
static void goto_caller_frame(void)
Definition: call-stack.h:264
void do_set_column(int c)
Definition: call-stack.h:438
static void create_instance(void)
Definition: call-stack.cc:83
octave_function * fcn
Definition: ov-class.cc:1743
static context_id current_context(void)
Definition: symtab.h:1165
octave_user_code * do_debug_user_code(void) const
Definition: call-stack.cc:242
octave_function * do_caller(void) const
Definition: call-stack.h:340
bool verbose
Definition: load-save.cc:654
static int debug_user_code_line(void)
Definition: call-stack.h:196
static int current_line(void)
Definition: call-stack.h:114
std::deque< stack_frame > cs
Definition: call-stack.h:328
symbol_table::scope_id do_current_scope(void) const
Definition: call-stack.h:351
static octave_user_code * caller_user_code(size_t nskip=0)
Definition: call-stack.h:172
static std::string fcn_file_name(const octave_value &fcn)
Definition: symtab.cc:1168
void do_goto_caller_frame(void)
Definition: call-stack.cc:539
static std::list< octave_call_stack::stack_frame > backtrace_frames(size_t nskip, octave_idx_type &curr_user_frame)
Definition: call-stack.h:304
static octave_function * caller(void)
Definition: call-stack.h:126
#define OCTINTERP_API
Definition: mexproto.h:69
static symbol_table::scope_id current_scope(void)
Definition: call-stack.h:147
static size_t current_frame(void)
Definition: call-stack.h:131
std::deque< stack_frame >::const_iterator const_iterator
Definition: call-stack.h:87
void do_set_line(int l)
Definition: call-stack.h:428
static llvm::LLVMContext & context
Definition: jit-typeinfo.cc:76
static octave_user_code * debug_user_code(void)
Definition: call-stack.h:190
int do_current_column(void) const
Definition: call-stack.cc:110
bool do_goto_frame(size_t n, bool verbose)
Definition: call-stack.cc:441
octave_function * do_element(size_t n)
Definition: call-stack.h:372
int do_caller_user_code_line(void) const
Definition: call-stack.cc:190
octave_value retval
Definition: data.cc:6294
static void clear(void)
Definition: call-stack.h:319
stack_frame(octave_function *fcn=0, symbol_table::scope_id scope=0, symbol_table::context_id context=0, size_t prev=0)
Definition: call-stack.h:55
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: call-stack.h:214
static void goto_base_frame(void)
Definition: call-stack.h:270
symbol_table::context_id do_current_context(void) const
Definition: call-stack.h:357
the sparsity preserving column transformation such that that defines the pivoting threshold can be given in which case it defines the c
Definition: lu.cc:138
octave_map do_backtrace(size_t nskip, octave_idx_type &curr_user_frame, bool print_subfn) const
Definition: call-stack.cc:402
static void set_column(int c)
Definition: call-stack.h:242
symbol_table::scope_id m_scope
Definition: call-stack.h:81
octave_call_stack(void)
Definition: call-stack.h:45
size_t do_num_user_code_frames(octave_idx_type &curr_user_frame) const
Definition: call-stack.cc:125
bool operator==(const dim_vector &a, const dim_vector &b)
Definition: dim-vector.h:538
static int caller_user_code_line(void)
Definition: call-stack.h:178
bool do_goto_frame_relative(int n, bool verbose)
Definition: call-stack.cc:469
octave::unwind_protect frame
Definition: graphics.cc:11584
static symbol_table::context_id current_context(void)
Definition: call-stack.h:152
static int current_column(void)
Definition: call-stack.h:120
static octave_function * element(size_t n)
Definition: call-stack.h:166
static int caller_user_code_column(void)
Definition: call-stack.h:184
static std::list< octave_call_stack::stack_frame > backtrace_frames(size_t nskip=0)
Definition: call-stack.h:294
void do_clear(void)
Definition: call-stack.h:475
size_t do_size(void)
Definition: call-stack.h:347
static void set_line(int l)
Definition: call-stack.h:236
static void pop(void)
Definition: call-stack.h:313
static octave_map empty_backtrace(void)
Definition: call-stack.cc:362
static octave_call_stack * instance
Definition: call-stack.h:332
static octave_map backtrace(size_t nskip, octave_idx_type &curr_user_frame, bool print_subfn=true)
Definition: call-stack.h:285
void do_pop(void)
Definition: call-stack.h:463
int do_current_line(void) const
Definition: call-stack.cc:96
static bool goto_frame_relative(int n, bool verbose=false)
Definition: call-stack.h:258
octave_user_code * do_caller_user_code(size_t nskip) const
Definition: call-stack.cc:162
stack_frame(const stack_frame &elt)
Definition: call-stack.h:61
static int debug_user_code_column(void)
Definition: call-stack.h:202
std::deque< stack_frame >::const_reverse_iterator const_reverse_iterator
Definition: call-stack.h:90
If this string is the system will ring the terminal sometimes it is useful to be able to print the original representation of the string
Definition: utils.cc:854
int do_debug_user_code_column(void) const
Definition: call-stack.cc:301
static void cleanup_instance(void)
Definition: call-stack.h:334
symbol_table::context_id m_context
Definition: call-stack.h:82
static void set_scope_and_context(scope_id scope, context_id context)
Definition: symtab.h:1193
octave_function * m_fcn
Definition: call-stack.h:78
void do_goto_base_frame(void)
Definition: call-stack.cc:577
static scope_id current_scope(void)
Definition: symtab.h:1163
static octave_map backtrace(size_t nskip=0)
Definition: call-stack.h:276