GNU Octave  3.8.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-2013 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 private:
80 
82  {
84  symbol_table::context_id c, size_t p = 0)
85  : fcn (f), line (-1), column (-1), scope (s), context (c), prev (p)
86  { }
87 
89  : fcn (elt.fcn), line (elt.line), column (elt.column),
90  scope (elt.scope), context (elt.context), prev (elt.prev)
91  { }
92 
94  int line;
95  int column;
98  size_t prev;
99  };
100 
101 protected:
102 
103  octave_call_stack (void) : cs (), curr_frame (0) { }
104 
105 public:
106 
107  typedef std::deque<call_stack_elt>::iterator iterator;
108  typedef std::deque<call_stack_elt>::const_iterator const_iterator;
109 
110  typedef std::deque<call_stack_elt>::reverse_iterator
112  typedef std::deque<call_stack_elt>::const_reverse_iterator
114 
115  static void create_instance (void);
116 
117  static bool instance_ok (void)
118  {
119  bool retval = true;
120 
121  if (! instance)
122  create_instance ();
123 
124  if (! instance)
125  {
126  ::error ("unable to create call stack object!");
127 
128  retval = false;
129  }
130 
131  return retval;
132  }
133 
134  // Current function (top of stack).
135  static octave_function *current (void)
136  {
137  return instance_ok () ? instance->do_current () : 0;
138  }
139 
140  // Current line in current function.
141  static int current_line (void)
142  {
143  return instance_ok () ? instance->do_current_line () : -1;
144  }
145 
146  // Current column in current function.
147  static int current_column (void)
148  {
149  return instance_ok () ? instance->do_current_column () : -1;
150  }
151 
152  // Line in user code caller.
153  static int caller_user_code_line (void)
154  {
155  return instance_ok () ? instance->do_caller_user_code_line () : -1;
156  }
157 
158  // Column in user code caller.
159  static int caller_user_code_column (void)
160  {
161  return instance_ok () ? instance->do_caller_user_code_column () : -1;
162  }
163 
164  // Caller function, may be built-in.
165  static octave_function *caller (void)
166  {
167  return instance_ok () ? instance->do_caller () : 0;
168  }
169 
170  static size_t current_frame (void)
171  {
172  return instance_ok () ? instance->do_current_frame () : 0;
173  }
174 
175  static size_t size (void)
176  {
177  return instance_ok () ? instance->do_size () : 0;
178  }
179 
180  static size_t num_user_code_frames (octave_idx_type& curr_user_frame)
181  {
182  return instance_ok ()
183  ? instance->do_num_user_code_frames (curr_user_frame) : 0;
184  }
185 
186  static symbol_table::scope_id current_scope (void)
187  {
188  return instance_ok () ? instance->do_current_scope () : 0;
189  }
190 
192  {
193  return instance_ok () ? instance->do_current_context () : 0;
194  }
195 
196  // Function at location N on the call stack (N == 0 is current), may
197  // be built-in.
198  static octave_function *element (size_t n)
199  {
200  return instance_ok () ? instance->do_element (n) : 0;
201  }
202 
203  // First user-defined function on the stack.
204  static octave_user_code *caller_user_code (size_t nskip = 0)
205  {
206  return instance_ok () ? instance->do_caller_user_code (nskip) : 0;
207  }
208 
209  static void
213  {
214  if (instance_ok ())
215  instance->do_push (f, scope, context);
216  }
217 
218  static void
221  {
222  if (instance_ok ())
223  instance->do_push (0, scope, context);
224  }
225 
226  static void set_location (int l, int c)
227  {
228  if (instance_ok ())
229  instance->do_set_location (l, c);
230  }
231 
232  static void set_line (int l)
233  {
234  if (instance_ok ())
235  instance->do_set_line (l);
236  }
237 
238  static void set_column (int c)
239  {
240  if (instance_ok ())
241  instance->do_set_column (c);
242  }
243 
244  static bool goto_frame (size_t n = 0, bool verbose = false)
245  {
246  return instance_ok () ? instance->do_goto_frame (n, verbose) : false;
247  }
248 
249  static void restore_frame (size_t n)
250  {
251  goto_frame (n);
252  }
253 
254  static bool goto_frame_relative (int n, bool verbose = false)
255  {
256  return instance_ok ()
257  ? instance->do_goto_frame_relative (n, verbose) : false;
258  }
259 
260  static void goto_caller_frame (void)
261  {
262  if (instance_ok ())
263  instance->do_goto_caller_frame ();
264  }
265 
266  static void goto_base_frame (void)
267  {
268  if (instance_ok ())
269  instance->do_goto_base_frame ();
270  }
271 
272  static octave_map backtrace (size_t nskip, octave_idx_type& curr_user_frame)
273  {
274  return instance_ok ()
275  ? instance->do_backtrace (nskip, curr_user_frame) : octave_map ();
276  }
277 
278  static octave_map empty_backtrace (void);
279 
280  static void pop (void)
281  {
282  if (instance_ok ())
283  instance->do_pop ();
284  }
285 
286  static void clear (void)
287  {
288  if (instance_ok ())
289  instance->do_clear ();
290  }
291 
292  static void backtrace_error_message (void)
293  {
294  if (instance_ok ())
295  instance->do_backtrace_error_message ();
296  }
297 
298 private:
299 
300  // The current call stack.
301  std::deque<call_stack_elt> cs;
302 
303  size_t curr_frame;
304 
306 
307  static void cleanup_instance (void) { delete instance; instance = 0; }
308 
309  int do_current_line (void) const;
310 
311  int do_current_column (void) const;
312 
313  int do_caller_user_code_line (void) const;
314 
315  int do_caller_user_code_column (void) const;
316 
317  octave_function *do_caller (void) const
318  {
319  return curr_frame > 1 ? cs[curr_frame-1].fcn : cs[0].fcn;
320  }
321 
322  size_t do_current_frame (void) { return curr_frame; }
323 
324  size_t do_size (void) { return cs.size (); }
325 
326  size_t do_num_user_code_frames (octave_idx_type& curr_user_frame) const;
327 
328  symbol_table::scope_id do_current_scope (void) const
329  {
330  return curr_frame > 0 && curr_frame < cs.size ()
331  ? cs[curr_frame].scope : 0;
332  }
333 
334  symbol_table::context_id do_current_context (void) const
335  {
336  return curr_frame > 0 && curr_frame < cs.size ()
337  ? cs[curr_frame].context : 0;
338  }
339 
340  octave_function *do_element (size_t n)
341  {
342  octave_function *retval = 0;
343 
344  if (cs.size () > n)
345  {
346  call_stack_elt& elt = cs[n];
347  retval = elt.fcn;
348  }
349 
350  return retval;
351  }
352 
353  octave_user_code *do_caller_user_code (size_t nskip) const;
354 
355  void do_push (octave_function *f, symbol_table::scope_id scope,
357  {
358  size_t prev_frame = curr_frame;
359  curr_frame = cs.size ();
360  cs.push_back (call_stack_elt (f, scope, context, prev_frame));
361  symbol_table::set_scope_and_context (scope, context);
362  }
363 
364  octave_function *do_current (void) const
365  {
366  octave_function *retval = 0;
367 
368  if (! cs.empty ())
369  {
370  const call_stack_elt& elt = cs[curr_frame];
371  retval = elt.fcn;
372  }
373 
374  return retval;
375  }
376 
377  void do_set_location (int l, int c)
378  {
379  if (! cs.empty ())
380  {
381  call_stack_elt& elt = cs.back ();
382 
383  elt.line = l;
384  elt.column = c;
385  }
386  }
387 
388  void do_set_line (int l)
389  {
390  if (! cs.empty ())
391  {
392  call_stack_elt& elt = cs.back ();
393 
394  elt.line = l;
395  }
396  }
397 
398  void do_set_column (int c)
399  {
400  if (! cs.empty ())
401  {
402  call_stack_elt& elt = cs.back ();
403 
404  elt.column = c;
405  }
406  }
407 
408  octave_map do_backtrace (size_t nskip,
409  octave_idx_type& curr_user_frame) const;
410 
411  bool do_goto_frame (size_t n, bool verbose);
412 
413  bool do_goto_frame_relative (int n, bool verbose);
414 
415  void do_goto_caller_frame (void);
416 
417  void do_goto_base_frame (void);
418 
419  void do_pop (void)
420  {
421  if (cs.size () > 1)
422  {
423  const call_stack_elt& elt = cs.back ();
424  curr_frame = elt.prev;
425  cs.pop_back ();
426  const call_stack_elt& new_elt = cs[curr_frame];
428  }
429  }
430 
431  void do_clear (void) { cs.clear (); }
432 
433  void do_backtrace_error_message (void) const;
434 };
435 
436 // Call a function with exceptions handled to avoid problems with
437 // errors while shutting down.
438 
439 #define OCTAVE_IGNORE_EXCEPTION(E) \
440  catch (E) \
441  { \
442  std::cerr << "error: ignoring " #E " while preparing to exit" << std::endl; \
443  recover_from_exception (); \
444  }
445 
446 #define OCTAVE_SAFE_CALL(F, ARGS) \
447  do \
448  { \
449  try \
450  { \
451  unwind_protect frame; \
452  \
453  frame.protect_var (Vdebug_on_error); \
454  frame.protect_var (Vdebug_on_warning); \
455  \
456  Vdebug_on_error = false; \
457  Vdebug_on_warning = false; \
458  \
459  F ARGS; \
460  } \
461  OCTAVE_IGNORE_EXCEPTION (octave_interrupt_exception) \
462  OCTAVE_IGNORE_EXCEPTION (octave_execution_exception) \
463  OCTAVE_IGNORE_EXCEPTION (std::bad_alloc) \
464  \
465  if (error_state) \
466  error_state = 0; \
467  } \
468  while (0)
469 
470 #endif