comparison libinterp/corefcn/call-stack.cc @ 31607:aac27ad79be6 stable

maint: Re-indent code after switch to using namespace macros. * build-env.h, build-env.in.cc, Cell.h, __betainc__.cc, __eigs__.cc, __ftp__.cc, __ichol__.cc, __ilu__.cc, __isprimelarge__.cc, __magick_read__.cc, __pchip_deriv__.cc, amd.cc, base-text-renderer.cc, base-text-renderer.h, besselj.cc, bitfcns.cc, bsxfun.cc, c-file-ptr-stream.h, call-stack.cc, call-stack.h, ccolamd.cc, cellfun.cc, chol.cc, colamd.cc, dasrt.cc, data.cc, debug.cc, defaults.cc, defaults.h, det.cc, display.cc, display.h, dlmread.cc, dynamic-ld.cc, dynamic-ld.h, ellipj.cc, environment.cc, environment.h, error.cc, error.h, errwarn.h, event-manager.cc, event-manager.h, event-queue.cc, event-queue.h, fcn-info.cc, fcn-info.h, fft.cc, fft2.cc, file-io.cc, filter.cc, find.cc, ft-text-renderer.cc, ft-text-renderer.h, gcd.cc, gl-render.cc, gl-render.h, gl2ps-print.cc, gl2ps-print.h, graphics-toolkit.cc, graphics-toolkit.h, graphics.cc, gsvd.cc, gtk-manager.cc, gtk-manager.h, help.cc, help.h, hook-fcn.cc, hook-fcn.h, input.cc, input.h, interpreter-private.cc, interpreter-private.h, interpreter.cc, interpreter.h, inv.cc, jsondecode.cc, jsonencode.cc, latex-text-renderer.cc, latex-text-renderer.h, load-path.cc, load-path.h, load-save.cc, load-save.h, lookup.cc, ls-hdf5.cc, ls-mat4.cc, ls-mat5.cc, lsode.cc, lu.cc, mappers.cc, matrix_type.cc, max.cc, mex.cc, mexproto.h, mxarray.h, mxtypes.in.h, oct-errno.in.cc, oct-hdf5-types.cc, oct-hist.cc, oct-hist.h, oct-map.cc, oct-map.h, oct-opengl.h, oct-prcstrm.h, oct-process.cc, oct-process.h, oct-stdstrm.h, oct-stream.cc, oct-stream.h, oct-strstrm.h, octave-default-image.h, ordqz.cc, ordschur.cc, pager.cc, pager.h, pinv.cc, pow2.cc, pr-output.cc, psi.cc, qr.cc, quadcc.cc, rand.cc, regexp.cc, settings.cc, settings.h, sighandlers.cc, sighandlers.h, sparse-xpow.cc, sqrtm.cc, stack-frame.cc, stack-frame.h, stream-euler.cc, strfns.cc, svd.cc, syminfo.cc, syminfo.h, symrcm.cc, symrec.cc, symrec.h, symscope.cc, symscope.h, symtab.cc, symtab.h, sysdep.cc, sysdep.h, text-engine.cc, text-engine.h, text-renderer.cc, text-renderer.h, time.cc, toplev.cc, typecast.cc, url-handle-manager.cc, url-handle-manager.h, urlwrite.cc, utils.cc, utils.h, variables.cc, variables.h, xdiv.cc, __delaunayn__.cc, __init_fltk__.cc, __init_gnuplot__.cc, __ode15__.cc, __voronoi__.cc, audioread.cc, convhulln.cc, gzip.cc, cdef-class.cc, cdef-class.h, cdef-fwd.h, cdef-manager.cc, cdef-manager.h, cdef-method.cc, cdef-method.h, cdef-object.cc, cdef-object.h, cdef-package.cc, cdef-package.h, cdef-property.cc, cdef-property.h, cdef-utils.cc, cdef-utils.h, ov-base-diag.cc, ov-base-int.cc, ov-base-mat.cc, ov-base-mat.h, ov-base-scalar.cc, ov-base.cc, ov-base.h, ov-bool-mat.cc, ov-bool-mat.h, ov-bool-sparse.cc, ov-bool.cc, ov-builtin.h, ov-cell.cc, ov-ch-mat.cc, ov-class.cc, ov-class.h, ov-classdef.cc, ov-classdef.h, ov-complex.cc, ov-cx-diag.cc, ov-cx-mat.cc, ov-cx-sparse.cc, ov-dld-fcn.cc, ov-dld-fcn.h, ov-fcn-handle.cc, ov-fcn-handle.h, ov-fcn.h, ov-float.cc, ov-flt-complex.cc, ov-flt-cx-diag.cc, ov-flt-cx-mat.cc, ov-flt-re-diag.cc, ov-flt-re-mat.cc, ov-flt-re-mat.h, ov-intx.h, ov-java.cc, ov-lazy-idx.cc, ov-legacy-range.cc, ov-magic-int.cc, ov-mex-fcn.cc, ov-mex-fcn.h, ov-null-mat.cc, ov-perm.cc, ov-range.cc, ov-re-diag.cc, ov-re-mat.cc, ov-re-mat.h, ov-re-sparse.cc, ov-scalar.cc, ov-str-mat.cc, ov-struct.cc, ov-typeinfo.cc, ov-typeinfo.h, ov-usr-fcn.cc, ov-usr-fcn.h, ov.cc, ov.h, ovl.h, octave.cc, octave.h, op-b-sbm.cc, op-bm-sbm.cc, op-cs-scm.cc, op-fm-fcm.cc, op-fs-fcm.cc, op-s-scm.cc, op-scm-cs.cc, op-scm-s.cc, op-sm-cs.cc, ops.h, anon-fcn-validator.cc, anon-fcn-validator.h, bp-table.cc, bp-table.h, comment-list.cc, comment-list.h, filepos.h, lex.h, oct-lvalue.cc, oct-lvalue.h, parse.h, profiler.cc, profiler.h, pt-anon-scopes.cc, pt-anon-scopes.h, pt-arg-list.cc, pt-arg-list.h, pt-args-block.cc, pt-args-block.h, pt-array-list.cc, pt-array-list.h, pt-assign.cc, pt-assign.h, pt-binop.cc, pt-binop.h, pt-bp.cc, pt-bp.h, pt-cbinop.cc, pt-cbinop.h, pt-cell.cc, pt-cell.h, pt-check.cc, pt-check.h, pt-classdef.cc, pt-classdef.h, pt-cmd.h, pt-colon.cc, pt-colon.h, pt-const.cc, pt-const.h, pt-decl.cc, pt-decl.h, pt-eval.cc, pt-eval.h, pt-except.cc, pt-except.h, pt-exp.cc, pt-exp.h, pt-fcn-handle.cc, pt-fcn-handle.h, pt-id.cc, pt-id.h, pt-idx.cc, pt-idx.h, pt-jump.h, pt-loop.cc, pt-loop.h, pt-mat.cc, pt-mat.h, pt-misc.cc, pt-misc.h, pt-pr-code.cc, pt-pr-code.h, pt-select.cc, pt-select.h, pt-spmd.cc, pt-spmd.h, pt-stmt.cc, pt-stmt.h, pt-tm-const.cc, pt-tm-const.h, pt-unop.cc, pt-unop.h, pt-walk.cc, pt-walk.h, pt.cc, pt.h, token.cc, token.h, Range.cc, Range.h, idx-vector.cc, idx-vector.h, range-fwd.h, CollocWt.cc, CollocWt.h, aepbalance.cc, aepbalance.h, chol.cc, chol.h, gepbalance.cc, gepbalance.h, gsvd.cc, gsvd.h, hess.cc, hess.h, lo-mappers.cc, lo-mappers.h, lo-specfun.cc, lo-specfun.h, lu.cc, lu.h, oct-convn.cc, oct-convn.h, oct-fftw.cc, oct-fftw.h, oct-norm.cc, oct-norm.h, oct-rand.cc, oct-rand.h, oct-spparms.cc, oct-spparms.h, qr.cc, qr.h, qrp.cc, qrp.h, randgamma.cc, randgamma.h, randmtzig.cc, randmtzig.h, randpoisson.cc, randpoisson.h, schur.cc, schur.h, sparse-chol.cc, sparse-chol.h, sparse-lu.cc, sparse-lu.h, sparse-qr.cc, sparse-qr.h, svd.cc, svd.h, child-list.cc, child-list.h, dir-ops.cc, dir-ops.h, file-ops.cc, file-ops.h, file-stat.cc, file-stat.h, lo-sysdep.cc, lo-sysdep.h, lo-sysinfo.cc, lo-sysinfo.h, mach-info.cc, mach-info.h, oct-env.cc, oct-env.h, oct-group.cc, oct-group.h, oct-password.cc, oct-password.h, oct-syscalls.cc, oct-syscalls.h, oct-time.cc, oct-time.h, oct-uname.cc, oct-uname.h, action-container.cc, action-container.h, base-list.h, cmd-edit.cc, cmd-edit.h, cmd-hist.cc, cmd-hist.h, f77-fcn.h, file-info.cc, file-info.h, lo-array-errwarn.cc, lo-array-errwarn.h, lo-hash.cc, lo-hash.h, lo-ieee.h, lo-regexp.cc, lo-regexp.h, lo-utils.cc, lo-utils.h, oct-base64.cc, oct-base64.h, oct-glob.cc, oct-glob.h, oct-inttypes.h, oct-mutex.cc, oct-mutex.h, oct-refcount.h, oct-shlib.cc, oct-shlib.h, oct-sparse.cc, oct-sparse.h, oct-string.h, octave-preserve-stream-state.h, pathsearch.cc, pathsearch.h, quit.cc, quit.h, unwind-prot.cc, unwind-prot.h, url-transfer.cc, url-transfer.h: Re-indent code after switch to using namespace macros.
author Rik <rik@octave.org>
date Thu, 01 Dec 2022 18:02:15 -0800
parents e88a07dec498
children 597f3ee61a48
comparison
equal deleted inserted replaced
31605:e88a07dec498 31607:aac27ad79be6
47 #include "symscope.h" 47 #include "symscope.h"
48 #include "variables.h" 48 #include "variables.h"
49 49
50 OCTAVE_BEGIN_NAMESPACE(octave) 50 OCTAVE_BEGIN_NAMESPACE(octave)
51 51
52 // Use static fields for the best efficiency. 52 // Use static fields for the best efficiency.
53 // NOTE: C++0x will allow these two to be merged into one. 53 // NOTE: C++0x will allow these two to be merged into one.
54 static const char *bt_fieldnames[] = 54 static const char *bt_fieldnames[] =
55 { "file", "name", "line", "column", nullptr }; 55 { "file", "name", "line", "column", nullptr };
56 56
57 static const octave_fields bt_fields (bt_fieldnames); 57 static const octave_fields bt_fields (bt_fieldnames);
58 58
59 call_stack::call_stack (tree_evaluator& evaluator) 59 call_stack::call_stack (tree_evaluator& evaluator)
60 : m_evaluator (evaluator), m_cs (), m_curr_frame (0), 60 : m_evaluator (evaluator), m_cs (), m_curr_frame (0),
61 m_max_stack_depth (1024), m_global_values () 61 m_max_stack_depth (1024), m_global_values ()
62 { 62 {
63 push (symbol_scope ("top scope")); 63 push (symbol_scope ("top scope"));
64 } 64 }
65 65
66 octave_function * call_stack::current_function (bool skip_first) const 66 octave_function *call_stack::current_function (bool skip_first) const
67 { 67 {
68 if (m_cs.empty ()) 68 if (m_cs.empty ())
69 error ("current_function: call stack is empty"); 69 error ("current_function: call stack is empty");
70 70
71 octave_function *fcn = nullptr; 71 octave_function *fcn = nullptr;
72 72
73 std::size_t idx = m_curr_frame; 73 std::size_t idx = m_curr_frame;
74 74
75 if (idx > 0 && skip_first) 75 if (idx > 0 && skip_first)
76 --idx;
77
78 while (true)
79 {
80 fcn = m_cs[idx]->function ();
81
82 if (fcn || idx == 0)
83 break;
84
76 --idx; 85 --idx;
77 86 }
78 while (true) 87
79 { 88 return fcn;
80 fcn = m_cs[idx]->function (); 89 }
81 90
82 if (fcn || idx == 0) 91 int call_stack::current_line (void) const
92 {
93 int retval = -1;
94
95 if (! m_cs.empty ())
96 {
97 const std::shared_ptr<stack_frame> elt = m_cs[m_curr_frame];
98 retval = elt->line ();
99 }
100
101 return retval;
102 }
103
104 int call_stack::current_column (void) const
105 {
106 int retval = -1;
107
108 if (! m_cs.empty ())
109 {
110 const std::shared_ptr<stack_frame> elt = m_cs[m_curr_frame];
111 retval = elt->column ();
112 }
113
114 return retval;
115 }
116
117 octave_user_code *call_stack::current_user_code (void) const
118 {
119 // Start at current frame.
120
121 std::size_t xframe = find_current_user_frame ();
122
123 if (xframe > 0)
124 {
125 const std::shared_ptr<stack_frame> elt = m_cs[xframe];
126
127 octave_function *f = elt->function ();
128
129 if (f && f->is_user_code ())
130 return dynamic_cast<octave_user_code *> (f);
131 }
132
133 return nullptr;
134 }
135
136 int call_stack::current_user_code_line (void) const
137 {
138 // Start at current frame.
139
140 std::size_t xframe = find_current_user_frame ();
141
142 if (xframe > 0)
143 {
144 const std::shared_ptr<stack_frame> elt = m_cs[xframe];
145
146 octave_function *f = elt->function ();
147
148 if (f && f->is_user_code ())
149 {
150 int line = elt->line ();
151
152 if (line > 0)
153 return line;
154 }
155 }
156
157 return -1;
158 }
159
160 int call_stack::current_user_code_column (void) const
161 {
162 // Start at current frame.
163
164 std::size_t xframe = find_current_user_frame ();
165
166 if (xframe > 0)
167 {
168 const std::shared_ptr<stack_frame> elt = m_cs[xframe];
169
170 octave_function *f = elt->function ();
171
172 if (f && f->is_user_code ())
173 {
174 int column = elt->column ();
175
176 if (column > 0)
177 return column;
178 }
179 }
180
181 return -1;
182 }
183
184 unwind_protect *call_stack::curr_fcn_unwind_protect_frame (void)
185 {
186 // Start at current frame.
187
188 std::size_t xframe = find_current_user_frame ();
189
190 if (xframe > 0)
191 {
192 const std::shared_ptr<stack_frame> elt = m_cs[xframe];
193
194 octave_function *f = elt->function ();
195
196 if (f && f->is_user_code ())
197 return elt->unwind_protect_frame ();
198 }
199
200 return nullptr;
201 }
202
203 octave_user_code *call_stack::debug_user_code (void) const
204 {
205 octave_user_code *retval = nullptr;
206
207 // This should never happen...
208 if (m_curr_frame == 0)
209 return retval;
210
211 std::size_t i = m_curr_frame;
212
213 while (i != 0)
214 {
215 const std::shared_ptr<stack_frame> elt = m_cs[i--];
216
217 octave_function *f = elt->function ();
218
219 if (f && f->is_user_code ())
220 {
221 retval = dynamic_cast<octave_user_code *> (f);
83 break; 222 break;
84 223 }
85 --idx; 224 }
86 } 225
87 226 return retval;
88 return fcn; 227 }
89 } 228
90 229 int call_stack::debug_user_code_line (void) const
91 int call_stack::current_line (void) const 230 {
92 { 231 int retval = -1;
93 int retval = -1; 232
94 233 // This should never happen...
95 if (! m_cs.empty ()) 234 if (m_curr_frame == 0)
96 {
97 const std::shared_ptr<stack_frame> elt = m_cs[m_curr_frame];
98 retval = elt->line ();
99 }
100
101 return retval; 235 return retval;
102 } 236
103 237 std::size_t i = m_curr_frame;
104 int call_stack::current_column (void) const 238
105 { 239 while (i != 0)
106 int retval = -1; 240 {
107 241 const std::shared_ptr<stack_frame> elt = m_cs[i--];
108 if (! m_cs.empty ()) 242
109 { 243 octave_function *f = elt->function ();
110 const std::shared_ptr<stack_frame> elt = m_cs[m_curr_frame]; 244
111 retval = elt->column (); 245 if (f && f->is_user_code ())
112 } 246 {
113 247 if (elt->line ())
248 {
249 retval = elt->line ();
250 break;
251 }
252 }
253 }
254
255 return retval;
256 }
257
258 int call_stack::debug_user_code_column (void) const
259 {
260 int retval = -1;
261
262 // This should never happen...
263 if (m_curr_frame == 0)
114 return retval; 264 return retval;
115 } 265
116 266 // Start looking with the caller of the calling debug function.
117 octave_user_code * call_stack::current_user_code (void) const 267 std::size_t i = m_curr_frame;
118 { 268
119 // Start at current frame. 269 while (i != 0)
120 270 {
121 std::size_t xframe = find_current_user_frame (); 271 const std::shared_ptr<stack_frame> elt = m_cs[i--];
122 272
123 if (xframe > 0) 273 octave_function *f = elt->function ();
124 { 274
125 const std::shared_ptr<stack_frame> elt = m_cs[xframe]; 275 if (f && f->is_user_code ())
126 276 {
127 octave_function *f = elt->function (); 277 if (elt->column ())
128 278 {
129 if (f && f->is_user_code ()) 279 retval = elt->column ();
130 return dynamic_cast<octave_user_code *> (f); 280 break;
131 } 281 }
132 282 }
133 return nullptr; 283 }
134 } 284
135 285 return retval;
136 int call_stack::current_user_code_line (void) const 286 }
137 { 287
138 // Start at current frame. 288 std::string call_stack::get_dispatch_class (void) const
139 289 {
140 std::size_t xframe = find_current_user_frame (); 290 return m_cs[m_curr_frame]->get_dispatch_class ();
141 291 }
142 if (xframe > 0) 292
143 { 293 void call_stack::set_dispatch_class (const std::string& class_name)
144 const std::shared_ptr<stack_frame> elt = m_cs[xframe]; 294 {
145 295 m_cs[m_curr_frame]->set_dispatch_class (class_name);
146 octave_function *f = elt->function (); 296 }
147 297
148 if (f && f->is_user_code ()) 298 bool call_stack::is_class_method_executing (std::string& dispatch_class) const
149 { 299 {
150 int line = elt->line (); 300 dispatch_class = "";
151 301
152 if (line > 0) 302 octave_function *f = current_function ();
153 return line; 303
154 } 304 bool retval = (f && f->is_class_method ());
155 } 305
156 306 if (retval)
157 return -1; 307 dispatch_class = f->dispatch_class ();
158 } 308
159 309 return retval;
160 int call_stack::current_user_code_column (void) const 310 }
161 { 311
162 // Start at current frame. 312 bool call_stack::is_class_constructor_executing (std::string& dispatch_class) const
163 313 {
164 std::size_t xframe = find_current_user_frame (); 314 dispatch_class = "";
165 315
166 if (xframe > 0) 316 octave_function *f = current_function ();
167 { 317
168 const std::shared_ptr<stack_frame> elt = m_cs[xframe]; 318 bool retval = (f && f->is_class_constructor ());
169 319
170 octave_function *f = elt->function (); 320 if (retval)
171 321 dispatch_class = f->dispatch_class ();
172 if (f && f->is_user_code ()) 322
173 { 323 return retval;
174 int column = elt->column (); 324 }
175 325
176 if (column > 0) 326 bool call_stack::all_scripts (void) const
177 return column; 327 {
178 } 328 bool retval = true;
179 } 329
180 330 auto p = m_cs.cend ();
181 return -1; 331
182 } 332 while (p != m_cs.cbegin ())
183 333 {
184 unwind_protect * call_stack::curr_fcn_unwind_protect_frame (void) 334 const std::shared_ptr<stack_frame> elt = *(--p);
185 { 335
186 // Start at current frame. 336 octave_function *f = elt->function ();
187 337
188 std::size_t xframe = find_current_user_frame (); 338 if (f && ! f->is_user_script ())
189 339 {
190 if (xframe > 0) 340 retval = false;
191 { 341 break;
192 const std::shared_ptr<stack_frame> elt = m_cs[xframe]; 342 }
193 343 }
194 octave_function *f = elt->function (); 344
195 345 return retval;
196 if (f && f->is_user_code ()) 346 }
197 return elt->unwind_protect_frame (); 347
198 } 348 void call_stack::get_new_frame_index_and_links
199 349 (std::size_t& new_frame_idx, std::shared_ptr<stack_frame>& parent_link,
200 return nullptr; 350 std::shared_ptr<stack_frame>& static_link) const
201 } 351 {
202 352 // FIXME: is there a better way?
203 octave_user_code * call_stack::debug_user_code (void) const 353
204 { 354 std::size_t prev_frame_idx = m_curr_frame;
205 octave_user_code *retval = nullptr; 355
206 356 new_frame_idx = m_cs.size ();
207 // This should never happen... 357
208 if (m_curr_frame == 0) 358 // m_max_stack_depth should never be less than zero.
209 return retval; 359 if (new_frame_idx > static_cast<std::size_t> (m_max_stack_depth))
210 360 error ("max_stack_depth exceeded");
211 std::size_t i = m_curr_frame; 361
212 362 // There can't be any links to previous frames if this is the first
213 while (i != 0) 363 // frame on the stack.
214 { 364
215 const std::shared_ptr<stack_frame> elt = m_cs[i--]; 365 if (new_frame_idx == 0)
216 366 return;
217 octave_function *f = elt->function (); 367
218 368 parent_link = m_cs[prev_frame_idx];
219 if (f && f->is_user_code ()) 369
220 { 370 octave_function *t_fcn = parent_link->function ();
221 retval = dynamic_cast<octave_user_code *> (f); 371
372 static_link = (t_fcn
373 ? (t_fcn->is_user_code ()
374 ? parent_link : parent_link->static_link ())
375 : parent_link);
376 }
377
378 void call_stack::push (const symbol_scope& scope)
379 {
380 std::size_t new_frame_idx;
381 std::shared_ptr<stack_frame> parent_link;
382 std::shared_ptr<stack_frame> static_link;
383
384 get_new_frame_index_and_links (new_frame_idx, parent_link, static_link);
385
386 std::shared_ptr<stack_frame>
387 new_frame (stack_frame::create (m_evaluator, scope, new_frame_idx,
388 parent_link, static_link));
389
390 m_cs.push_back (new_frame);
391
392 m_curr_frame = new_frame_idx;
393 }
394
395 void call_stack::push (octave_user_function *fcn,
396 const std::shared_ptr<stack_frame>& closure_frames)
397 {
398 std::size_t new_frame_idx;
399 std::shared_ptr<stack_frame> parent_link;
400 std::shared_ptr<stack_frame> static_link;
401
402 get_new_frame_index_and_links (new_frame_idx, parent_link, static_link);
403
404 std::shared_ptr<stack_frame>
405 new_frame (stack_frame::create (m_evaluator, fcn, new_frame_idx,
406 parent_link, static_link,
407 closure_frames));
408
409 m_cs.push_back (new_frame);
410
411 m_curr_frame = new_frame_idx;
412 }
413
414 void call_stack::push (octave_user_function *fcn,
415 const stack_frame::local_vars_map& local_vars,
416 const std::shared_ptr<stack_frame>& closure_frames)
417 {
418 std::size_t new_frame_idx;
419 std::shared_ptr<stack_frame> parent_link;
420 std::shared_ptr<stack_frame> static_link;
421
422 get_new_frame_index_and_links (new_frame_idx, parent_link, static_link);
423
424 std::shared_ptr<stack_frame>
425 new_frame (stack_frame::create (m_evaluator, fcn, new_frame_idx,
426 parent_link, static_link, local_vars,
427 closure_frames));
428
429 m_cs.push_back (new_frame);
430
431 m_curr_frame = new_frame_idx;
432 }
433
434 void call_stack::push (octave_user_script *script)
435 {
436 std::size_t new_frame_idx;
437 std::shared_ptr<stack_frame> parent_link;
438 std::shared_ptr<stack_frame> static_link;
439
440 get_new_frame_index_and_links (new_frame_idx, parent_link, static_link);
441
442 std::shared_ptr<stack_frame>
443 new_frame (stack_frame::create (m_evaluator, script, new_frame_idx,
444 parent_link, static_link));
445
446 m_cs.push_back (new_frame);
447
448 m_curr_frame = new_frame_idx;
449 }
450
451 void call_stack::push (octave_function *fcn)
452 {
453 std::size_t new_frame_idx;
454 std::shared_ptr<stack_frame> parent_link;
455 std::shared_ptr<stack_frame> static_link;
456
457 get_new_frame_index_and_links (new_frame_idx, parent_link, static_link);
458
459 std::shared_ptr<stack_frame>
460 new_frame (stack_frame::create (m_evaluator, fcn, new_frame_idx,
461 parent_link, static_link));
462
463 m_cs.push_back (new_frame);
464
465 m_curr_frame = new_frame_idx;
466 }
467
468 bool call_stack::goto_frame (std::size_t n, bool verbose)
469 {
470 bool retval = false;
471
472 if (n < m_cs.size ())
473 {
474 retval = true;
475
476 m_curr_frame = n;
477
478 if (verbose)
479 {
480 const std::shared_ptr<stack_frame> elt = m_cs[n];
481
482 elt->display_stopped_in_message (octave_stdout);
483 }
484 }
485
486 return retval;
487 }
488
489 std::size_t call_stack::find_current_user_frame (void) const
490 {
491 std::size_t user_frame = m_curr_frame;
492
493 std::shared_ptr<stack_frame> frm = m_cs[user_frame];
494
495 if (! (frm->is_user_fcn_frame () || frm->is_user_script_frame ()
496 || frm->is_scope_frame ()))
497 {
498 frm = frm->static_link ();
499
500 user_frame = frm->index ();
501 }
502
503 return user_frame;
504 }
505
506 std::shared_ptr<stack_frame> call_stack::current_user_frame (void) const
507 {
508 std::size_t frame = find_current_user_frame ();
509
510 return m_cs[frame];
511 }
512
513 // Go to the Nth frame (up if N is negative or down if positive) in
514 // the call stack that corresponds to a script, function, or scope
515 // beginning with the frame indexed by START.
516
517 std::size_t call_stack::dbupdown (std::size_t start, int n, bool verbose)
518 {
519 if (start >= m_cs.size ())
520 error ("invalid stack frame");
521
522 // Can't go up from here.
523
524 if (start == 0 && n < 0)
525 {
526 if (verbose)
527 m_cs[start]->display_stopped_in_message (octave_stdout);
528
529 return start;
530 }
531
532 std::shared_ptr<stack_frame> frm = m_cs[start];
533
534 if (! (frm && (frm->is_user_fcn_frame ()
535 || frm->is_user_script_frame ()
536 || frm->is_scope_frame ())))
537 error ("call_stack::dbupdown: invalid initial frame in call stack!");
538
539 // Use index into the call stack to begin the search. At this point
540 // we iterate up or down using indexing instead of static links
541 // because ... FIXME: it's a bit complicated, but deserves
542 // explanation. May be easiest with some pictures of the call stack
543 // for an example or two.
544
545 std::size_t xframe = frm->index ();
546
547 if (n == 0)
548 {
549 if (verbose)
550 frm->display_stopped_in_message (octave_stdout);
551
552 return xframe;
553 }
554
555 int incr = 0;
556
557 if (n < 0)
558 {
559 incr = -1;
560 n = -n;
561 }
562 else if (n > 0)
563 incr = 1;
564
565 std::size_t last_good_frame = 0;
566
567 while (true)
568 {
569 frm = m_cs[xframe];
570
571 if (frm->is_user_fcn_frame () || frm->is_user_script_frame ()
572 || frm->is_scope_frame ())
573 {
574 last_good_frame = xframe;
575
576 if (n == 0)
222 break; 577 break;
223 } 578
224 } 579 n--;
225 580 }
226 return retval; 581
227 } 582 xframe += incr;
228 583
229 int call_stack::debug_user_code_line (void) const 584 if (xframe == 0)
230 { 585 {
231 int retval = -1; 586 last_good_frame = 0;
232
233 // This should never happen...
234 if (m_curr_frame == 0)
235 return retval;
236
237 std::size_t i = m_curr_frame;
238
239 while (i != 0)
240 {
241 const std::shared_ptr<stack_frame> elt = m_cs[i--];
242
243 octave_function *f = elt->function ();
244
245 if (f && f->is_user_code ())
246 {
247 if (elt->line ())
248 {
249 retval = elt->line ();
250 break;
251 }
252 }
253 }
254
255 return retval;
256 }
257
258 int call_stack::debug_user_code_column (void) const
259 {
260 int retval = -1;
261
262 // This should never happen...
263 if (m_curr_frame == 0)
264 return retval;
265
266 // Start looking with the caller of the calling debug function.
267 std::size_t i = m_curr_frame;
268
269 while (i != 0)
270 {
271 const std::shared_ptr<stack_frame> elt = m_cs[i--];
272
273 octave_function *f = elt->function ();
274
275 if (f && f->is_user_code ())
276 {
277 if (elt->column ())
278 {
279 retval = elt->column ();
280 break;
281 }
282 }
283 }
284
285 return retval;
286 }
287
288 std::string call_stack::get_dispatch_class (void) const
289 {
290 return m_cs[m_curr_frame]->get_dispatch_class ();
291 }
292
293 void call_stack::set_dispatch_class (const std::string& class_name)
294 {
295 m_cs[m_curr_frame]->set_dispatch_class (class_name);
296 }
297
298 bool call_stack::is_class_method_executing (std::string& dispatch_class) const
299 {
300 dispatch_class = "";
301
302 octave_function *f = current_function ();
303
304 bool retval = (f && f->is_class_method ());
305
306 if (retval)
307 dispatch_class = f->dispatch_class ();
308
309 return retval;
310 }
311
312 bool call_stack::is_class_constructor_executing (std::string& dispatch_class) const
313 {
314 dispatch_class = "";
315
316 octave_function *f = current_function ();
317
318 bool retval = (f && f->is_class_constructor ());
319
320 if (retval)
321 dispatch_class = f->dispatch_class ();
322
323 return retval;
324 }
325
326 bool call_stack::all_scripts (void) const
327 {
328 bool retval = true;
329
330 auto p = m_cs.cend ();
331
332 while (p != m_cs.cbegin ())
333 {
334 const std::shared_ptr<stack_frame> elt = *(--p);
335
336 octave_function *f = elt->function ();
337
338 if (f && ! f->is_user_script ())
339 {
340 retval = false;
341 break;
342 }
343 }
344
345 return retval;
346 }
347
348 void call_stack::get_new_frame_index_and_links
349 (std::size_t& new_frame_idx, std::shared_ptr<stack_frame>& parent_link,
350 std::shared_ptr<stack_frame>& static_link) const
351 {
352 // FIXME: is there a better way?
353
354 std::size_t prev_frame_idx = m_curr_frame;
355
356 new_frame_idx = m_cs.size ();
357
358 // m_max_stack_depth should never be less than zero.
359 if (new_frame_idx > static_cast<std::size_t> (m_max_stack_depth))
360 error ("max_stack_depth exceeded");
361
362 // There can't be any links to previous frames if this is the first
363 // frame on the stack.
364
365 if (new_frame_idx == 0)
366 return;
367
368 parent_link = m_cs[prev_frame_idx];
369
370 octave_function *t_fcn = parent_link->function ();
371
372 static_link = (t_fcn
373 ? (t_fcn->is_user_code ()
374 ? parent_link : parent_link->static_link ())
375 : parent_link);
376 }
377
378 void call_stack::push (const symbol_scope& scope)
379 {
380 std::size_t new_frame_idx;
381 std::shared_ptr<stack_frame> parent_link;
382 std::shared_ptr<stack_frame> static_link;
383
384 get_new_frame_index_and_links (new_frame_idx, parent_link, static_link);
385
386 std::shared_ptr<stack_frame>
387 new_frame (stack_frame::create (m_evaluator, scope, new_frame_idx,
388 parent_link, static_link));
389
390 m_cs.push_back (new_frame);
391
392 m_curr_frame = new_frame_idx;
393 }
394
395 void call_stack::push (octave_user_function *fcn,
396 const std::shared_ptr<stack_frame>& closure_frames)
397 {
398 std::size_t new_frame_idx;
399 std::shared_ptr<stack_frame> parent_link;
400 std::shared_ptr<stack_frame> static_link;
401
402 get_new_frame_index_and_links (new_frame_idx, parent_link, static_link);
403
404 std::shared_ptr<stack_frame>
405 new_frame (stack_frame::create (m_evaluator, fcn, new_frame_idx,
406 parent_link, static_link,
407 closure_frames));
408
409 m_cs.push_back (new_frame);
410
411 m_curr_frame = new_frame_idx;
412 }
413
414 void call_stack::push (octave_user_function *fcn,
415 const stack_frame::local_vars_map& local_vars,
416 const std::shared_ptr<stack_frame>& closure_frames)
417 {
418 std::size_t new_frame_idx;
419 std::shared_ptr<stack_frame> parent_link;
420 std::shared_ptr<stack_frame> static_link;
421
422 get_new_frame_index_and_links (new_frame_idx, parent_link, static_link);
423
424 std::shared_ptr<stack_frame>
425 new_frame (stack_frame::create (m_evaluator, fcn, new_frame_idx,
426 parent_link, static_link, local_vars,
427 closure_frames));
428
429 m_cs.push_back (new_frame);
430
431 m_curr_frame = new_frame_idx;
432 }
433
434 void call_stack::push (octave_user_script *script)
435 {
436 std::size_t new_frame_idx;
437 std::shared_ptr<stack_frame> parent_link;
438 std::shared_ptr<stack_frame> static_link;
439
440 get_new_frame_index_and_links (new_frame_idx, parent_link, static_link);
441
442 std::shared_ptr<stack_frame>
443 new_frame (stack_frame::create (m_evaluator, script, new_frame_idx,
444 parent_link, static_link));
445
446 m_cs.push_back (new_frame);
447
448 m_curr_frame = new_frame_idx;
449 }
450
451 void call_stack::push (octave_function *fcn)
452 {
453 std::size_t new_frame_idx;
454 std::shared_ptr<stack_frame> parent_link;
455 std::shared_ptr<stack_frame> static_link;
456
457 get_new_frame_index_and_links (new_frame_idx, parent_link, static_link);
458
459 std::shared_ptr<stack_frame>
460 new_frame (stack_frame::create (m_evaluator, fcn, new_frame_idx,
461 parent_link, static_link));
462
463 m_cs.push_back (new_frame);
464
465 m_curr_frame = new_frame_idx;
466 }
467
468 bool call_stack::goto_frame (std::size_t n, bool verbose)
469 {
470 bool retval = false;
471
472 if (n < m_cs.size ())
473 {
474 retval = true;
475
476 m_curr_frame = n;
477
478 if (verbose)
479 {
480 const std::shared_ptr<stack_frame> elt = m_cs[n];
481
482 elt->display_stopped_in_message (octave_stdout);
483 }
484 }
485
486 return retval;
487 }
488
489 std::size_t call_stack::find_current_user_frame (void) const
490 {
491 std::size_t user_frame = m_curr_frame;
492
493 std::shared_ptr<stack_frame> frm = m_cs[user_frame];
494
495 if (! (frm->is_user_fcn_frame () || frm->is_user_script_frame ()
496 || frm->is_scope_frame ()))
497 {
498 frm = frm->static_link ();
499
500 user_frame = frm->index ();
501 }
502
503 return user_frame;
504 }
505
506 std::shared_ptr<stack_frame> call_stack::current_user_frame (void) const
507 {
508 std::size_t frame = find_current_user_frame ();
509
510 return m_cs[frame];
511 }
512
513 // Go to the Nth frame (up if N is negative or down if positive) in
514 // the call stack that corresponds to a script, function, or scope
515 // beginning with the frame indexed by START.
516
517 std::size_t call_stack::dbupdown (std::size_t start, int n, bool verbose)
518 {
519 if (start >= m_cs.size ())
520 error ("invalid stack frame");
521
522 // Can't go up from here.
523
524 if (start == 0 && n < 0)
525 {
526 if (verbose)
527 m_cs[start]->display_stopped_in_message (octave_stdout);
528
529 return start;
530 }
531
532 std::shared_ptr<stack_frame> frm = m_cs[start];
533
534 if (! (frm && (frm->is_user_fcn_frame ()
535 || frm->is_user_script_frame ()
536 || frm->is_scope_frame ())))
537 error ("call_stack::dbupdown: invalid initial frame in call stack!");
538
539 // Use index into the call stack to begin the search. At this point
540 // we iterate up or down using indexing instead of static links
541 // because ... FIXME: it's a bit complicated, but deserves
542 // explanation. May be easiest with some pictures of the call stack
543 // for an example or two.
544
545 std::size_t xframe = frm->index ();
546
547 if (n == 0)
548 {
549 if (verbose)
550 frm->display_stopped_in_message (octave_stdout);
551
552 return xframe;
553 }
554
555 int incr = 0;
556
557 if (n < 0)
558 {
559 incr = -1;
560 n = -n;
561 }
562 else if (n > 0)
563 incr = 1;
564
565 std::size_t last_good_frame = 0;
566
567 while (true)
568 {
569 frm = m_cs[xframe];
570
571 if (frm->is_user_fcn_frame () || frm->is_user_script_frame ()
572 || frm->is_scope_frame ())
573 {
574 last_good_frame = xframe;
575
576 if (n == 0)
577 break;
578
579 n--;
580 }
581
582 xframe += incr;
583
584 if (xframe == 0)
585 {
586 last_good_frame = 0;
587 break;
588 }
589
590 if (xframe == m_cs.size ())
591 break; 587 break;
592 } 588 }
593 589
594 if (verbose) 590 if (xframe == m_cs.size ())
595 m_cs[last_good_frame]->display_stopped_in_message (octave_stdout); 591 break;
596 592 }
597 return last_good_frame; 593
598 } 594 if (verbose)
599 595 m_cs[last_good_frame]->display_stopped_in_message (octave_stdout);
600 // Like dbupdown above but find the starting frame automatically from 596
601 // the current frame. If the current frame is already a user 597 return last_good_frame;
602 // function, script, or scope frame, use that. Otherwise, follow 598 }
603 // the static link for the current frame. If that is not a user 599
604 // function, script or scope frame then there is an error in the 600 // Like dbupdown above but find the starting frame automatically from
605 // implementation. 601 // the current frame. If the current frame is already a user
606 602 // function, script, or scope frame, use that. Otherwise, follow
607 std::size_t call_stack::dbupdown (int n, bool verbose) 603 // the static link for the current frame. If that is not a user
608 { 604 // function, script or scope frame then there is an error in the
609 std::size_t start = find_current_user_frame (); 605 // implementation.
610 606
611 return dbupdown (start, n, verbose); 607 std::size_t call_stack::dbupdown (int n, bool verbose)
612 } 608 {
613 609 std::size_t start = find_current_user_frame ();
614 // May be used to temporarily change the value ov m_curr_frame inside 610
615 // a function like evalin. If used in a function like dbup, the new 611 return dbupdown (start, n, verbose);
616 // value of m_curr_frame would be wiped out when dbup returns and the 612 }
617 // stack frame for dbup is popped. 613
618 614 // May be used to temporarily change the value ov m_curr_frame inside
619 void call_stack::goto_caller_frame (void) 615 // a function like evalin. If used in a function like dbup, the new
620 { 616 // value of m_curr_frame would be wiped out when dbup returns and the
621 std::size_t start = find_current_user_frame (); 617 // stack frame for dbup is popped.
622 618
623 std::shared_ptr<stack_frame> caller_frame = m_cs[start]->static_link (); 619 void call_stack::goto_caller_frame (void)
624 620 {
625 // Allow evalin ('caller', ...) to work when called from the 621 std::size_t start = find_current_user_frame ();
626 // top-level prompt. 622
627 623 std::shared_ptr<stack_frame> caller_frame = m_cs[start]->static_link ();
628 m_curr_frame = caller_frame ? caller_frame->index () : 0; 624
629 } 625 // Allow evalin ('caller', ...) to work when called from the
630 626 // top-level prompt.
631 void call_stack::goto_base_frame (void) 627
632 { 628 m_curr_frame = caller_frame ? caller_frame->index () : 0;
633 if (m_curr_frame > 0) 629 }
634 m_curr_frame = 0; 630
635 } 631 void call_stack::goto_base_frame (void)
636 632 {
637 std::list<std::shared_ptr<stack_frame>> 633 if (m_curr_frame > 0)
638 call_stack::backtrace_frames (octave_idx_type& curr_user_frame) const 634 m_curr_frame = 0;
639 { 635 }
640 std::list<std::shared_ptr<stack_frame>> frames; 636
641 637 std::list<std::shared_ptr<stack_frame>>
642 // curr_frame is the index to the current frame in the overall call 638 call_stack::backtrace_frames (octave_idx_type& curr_user_frame) const
643 // stack, which includes any compiled function frames and scope 639 {
644 // frames. The curr_user_frame value we set is the index into the 640 std::list<std::shared_ptr<stack_frame>> frames;
645 // subset of frames returned in the octave_map object. 641
646 642 // curr_frame is the index to the current frame in the overall call
647 std::size_t curr_frame = find_current_user_frame (); 643 // stack, which includes any compiled function frames and scope
648 644 // frames. The curr_user_frame value we set is the index into the
649 // Don't include top-level stack frame in the list. 645 // subset of frames returned in the octave_map object.
650 646
651 for (std::size_t n = m_cs.size () - 1; n > 0; n--) 647 std::size_t curr_frame = find_current_user_frame ();
652 { 648
653 std::shared_ptr<stack_frame> frm = m_cs[n]; 649 // Don't include top-level stack frame in the list.
654 650
655 if (frm->is_user_script_frame () || frm->is_user_fcn_frame () 651 for (std::size_t n = m_cs.size () - 1; n > 0; n--)
656 || frm->is_scope_frame ()) 652 {
657 { 653 std::shared_ptr<stack_frame> frm = m_cs[n];
658 if (frm->index () == curr_frame) 654
659 curr_user_frame = frames.size (); 655 if (frm->is_user_script_frame () || frm->is_user_fcn_frame ()
660 656 || frm->is_scope_frame ())
661 frames.push_back (frm); 657 {
662 } 658 if (frm->index () == curr_frame)
663 659 curr_user_frame = frames.size ();
664 if (n == 0) 660
665 break; 661 frames.push_back (frm);
666 } 662 }
667 663
668 return frames; 664 if (n == 0)
669 } 665 break;
670 666 }
671 std::list<std::shared_ptr<stack_frame>> 667
672 call_stack::backtrace_frames (void) const 668 return frames;
673 { 669 }
674 octave_idx_type curr_user_frame = -1; 670
675 671 std::list<std::shared_ptr<stack_frame>>
676 return backtrace_frames (curr_user_frame); 672 call_stack::backtrace_frames (void) const
677 } 673 {
678 674 octave_idx_type curr_user_frame = -1;
679 std::list<frame_info> 675
680 call_stack::backtrace_info (octave_idx_type& curr_user_frame, 676 return backtrace_frames (curr_user_frame);
681 bool print_subfn) const 677 }
682 { 678
683 std::list<std::shared_ptr<stack_frame>> frames 679 std::list<frame_info>
684 = backtrace_frames (curr_user_frame); 680 call_stack::backtrace_info (octave_idx_type& curr_user_frame,
685 681 bool print_subfn) const
686 std::list<frame_info> retval; 682 {
687 683 std::list<std::shared_ptr<stack_frame>> frames
688 for (const auto& frm : frames) 684 = backtrace_frames (curr_user_frame);
689 { 685
690 if (frm->is_user_script_frame () || frm->is_user_fcn_frame () 686 std::list<frame_info> retval;
691 || frm->is_scope_frame ()) 687
692 { 688 for (const auto& frm : frames)
693 retval.push_back (frame_info (frm->fcn_file_name (), 689 {
694 frm->fcn_name (print_subfn), 690 if (frm->is_user_script_frame () || frm->is_user_fcn_frame ()
695 frm->line (), frm->column ())); 691 || frm->is_scope_frame ())
696 } 692 {
697 } 693 retval.push_back (frame_info (frm->fcn_file_name (),
698 694 frm->fcn_name (print_subfn),
699 return retval; 695 frm->line (), frm->column ()));
700 } 696 }
701 697 }
702 std::list<frame_info> call_stack::backtrace_info (void) const 698
703 { 699 return retval;
704 octave_idx_type curr_user_frame = -1; 700 }
705 701
706 return backtrace_info (curr_user_frame, true); 702 std::list<frame_info> call_stack::backtrace_info (void) const
707 } 703 {
708 704 octave_idx_type curr_user_frame = -1;
709 octave_map call_stack::backtrace (octave_idx_type& curr_user_frame, 705
710 bool print_subfn) const 706 return backtrace_info (curr_user_frame, true);
711 { 707 }
712 std::list<std::shared_ptr<stack_frame>> frames 708
713 = backtrace_frames (curr_user_frame); 709 octave_map call_stack::backtrace (octave_idx_type& curr_user_frame,
714 710 bool print_subfn) const
715 std::size_t nframes = frames.size (); 711 {
716 712 std::list<std::shared_ptr<stack_frame>> frames
717 octave_map retval (dim_vector (nframes, 1), bt_fields); 713 = backtrace_frames (curr_user_frame);
718 714
719 Cell& file = retval.contents (0); 715 std::size_t nframes = frames.size ();
720 Cell& name = retval.contents (1); 716
721 Cell& line = retval.contents (2); 717 octave_map retval (dim_vector (nframes, 1), bt_fields);
722 Cell& column = retval.contents (3); 718
723 719 Cell& file = retval.contents (0);
724 octave_idx_type k = 0; 720 Cell& name = retval.contents (1);
725 721 Cell& line = retval.contents (2);
726 for (const auto& frm : frames) 722 Cell& column = retval.contents (3);
727 { 723
728 if (frm->is_user_script_frame () || frm->is_user_fcn_frame () 724 octave_idx_type k = 0;
729 || frm->is_scope_frame ()) 725
730 { 726 for (const auto& frm : frames)
731 file(k) = frm->fcn_file_name (); 727 {
732 name(k) = frm->fcn_name (print_subfn); 728 if (frm->is_user_script_frame () || frm->is_user_fcn_frame ()
733 line(k) = frm->line (); 729 || frm->is_scope_frame ())
734 column(k) = frm->column (); 730 {
735 731 file(k) = frm->fcn_file_name ();
736 k++; 732 name(k) = frm->fcn_name (print_subfn);
737 } 733 line(k) = frm->line ();
738 } 734 column(k) = frm->column ();
739 735
740 return retval; 736 k++;
741 } 737 }
742 738 }
743 octave_map call_stack::backtrace (void) const 739
744 { 740 return retval;
745 octave_idx_type curr_user_frame = -1; 741 }
746 742
747 return backtrace (curr_user_frame, true); 743 octave_map call_stack::backtrace (void) const
748 } 744 {
749 745 octave_idx_type curr_user_frame = -1;
750 octave_map call_stack::empty_backtrace (void) const 746
751 { 747 return backtrace (curr_user_frame, true);
752 return octave_map (dim_vector (0, 1), bt_fields); 748 }
753 } 749
754 750 octave_map call_stack::empty_backtrace (void) const
755 void call_stack::pop (void) 751 {
756 { 752 return octave_map (dim_vector (0, 1), bt_fields);
757 // Never pop top scope. 753 }
758 // FIXME: is it possible for this case to happen? 754
759 755 void call_stack::pop (void)
760 if (m_cs.size () > 1) 756 {
761 { 757 // Never pop top scope.
762 std::shared_ptr<stack_frame> elt = m_cs.back (); 758 // FIXME: is it possible for this case to happen?
763 759
764 std::shared_ptr<stack_frame> caller = elt->parent_link (); 760 if (m_cs.size () > 1)
765 761 {
766 m_curr_frame = caller->index (); 762 std::shared_ptr<stack_frame> elt = m_cs.back ();
767 763
768 if (elt->is_closure_context ()) 764 std::shared_ptr<stack_frame> caller = elt->parent_link ();
769 elt->break_closure_cycles (elt); 765
770 766 m_curr_frame = caller->index ();
771 m_cs.pop_back (); 767
772 } 768 if (elt->is_closure_context ())
773 } 769 elt->break_closure_cycles (elt);
774 770
775 void call_stack::clear (void) 771 m_cs.pop_back ();
776 { 772 }
777 while (! m_cs.empty ()) 773 }
778 pop (); 774
779 } 775 void call_stack::clear (void)
780 776 {
781 symbol_info_list call_stack::all_variables (void) 777 while (! m_cs.empty ())
782 { 778 pop ();
783 return m_cs[m_curr_frame]->all_variables (); 779 }
784 } 780
785 781 symbol_info_list call_stack::all_variables (void)
786 std::list<std::string> call_stack::global_variable_names (void) const 782 {
787 { 783 return m_cs[m_curr_frame]->all_variables ();
788 std::list<std::string> retval; 784 }
789 785
790 for (const auto& nm_ov : m_global_values) 786 std::list<std::string> call_stack::global_variable_names (void) const
791 { 787 {
792 if (nm_ov.second.is_defined ()) 788 std::list<std::string> retval;
793 retval.push_back (nm_ov.first); 789
794 } 790 for (const auto& nm_ov : m_global_values)
795 791 {
796 retval.sort (); 792 if (nm_ov.second.is_defined ())
797 793 retval.push_back (nm_ov.first);
798 return retval; 794 }
799 } 795
800 796 retval.sort ();
801 std::list<std::string> call_stack::top_level_variable_names (void) const 797
802 { 798 return retval;
803 return m_cs[0]->variable_names (); 799 }
804 } 800
805 801 std::list<std::string> call_stack::top_level_variable_names (void) const
806 std::list<std::string> call_stack::variable_names (void) const 802 {
807 { 803 return m_cs[0]->variable_names ();
808 return m_cs[m_curr_frame]->variable_names (); 804 }
809 } 805
810 806 std::list<std::string> call_stack::variable_names (void) const
811 void call_stack::clear_global_variable (const std::string& name) 807 {
812 { 808 return m_cs[m_curr_frame]->variable_names ();
813 auto p = m_global_values.find (name); 809 }
814 810
815 if (p != m_global_values.end ()) 811 void call_stack::clear_global_variable (const std::string& name)
816 p->second = octave_value (); 812 {
817 } 813 auto p = m_global_values.find (name);
818 814
819 void call_stack::clear_global_variable_pattern (const std::string& pattern) 815 if (p != m_global_values.end ())
820 { 816 p->second = octave_value ();
821 glob_match pat (pattern); 817 }
822 818
823 for (auto& nm_ov : m_global_values) 819 void call_stack::clear_global_variable_pattern (const std::string& pattern)
824 { 820 {
825 if (pat.match (nm_ov.first)) 821 glob_match pat (pattern);
826 nm_ov.second = octave_value (); 822
827 } 823 for (auto& nm_ov : m_global_values)
828 } 824 {
829 825 if (pat.match (nm_ov.first))
830 void call_stack::clear_global_variable_regexp (const std::string& pattern) 826 nm_ov.second = octave_value ();
831 { 827 }
832 regexp pat (pattern); 828 }
833 829
834 for (auto& nm_ov : m_global_values) 830 void call_stack::clear_global_variable_regexp (const std::string& pattern)
835 { 831 {
836 if (pat.is_match (nm_ov.first)) 832 regexp pat (pattern);
837 nm_ov.second = octave_value (); 833
838 } 834 for (auto& nm_ov : m_global_values)
839 } 835 {
840 836 if (pat.is_match (nm_ov.first))
841 void call_stack::clear_global_variables (void) 837 nm_ov.second = octave_value ();
842 { 838 }
843 for (auto& nm_ov : m_global_values) 839 }
844 nm_ov.second = octave_value (); 840
845 } 841 void call_stack::clear_global_variables (void)
846 842 {
847 symbol_info_list 843 for (auto& nm_ov : m_global_values)
848 call_stack::glob_symbol_info (const std::string& pattern) const 844 nm_ov.second = octave_value ();
849 { 845 }
850 return m_cs[m_curr_frame]->glob_symbol_info (pattern); 846
851 } 847 symbol_info_list
852 848 call_stack::glob_symbol_info (const std::string& pattern) const
853 symbol_info_list 849 {
854 call_stack::regexp_symbol_info (const std::string& pattern) const 850 return m_cs[m_curr_frame]->glob_symbol_info (pattern);
855 { 851 }
856 return m_cs[m_curr_frame]->regexp_symbol_info (pattern); 852
857 } 853 symbol_info_list
858 854 call_stack::regexp_symbol_info (const std::string& pattern) const
859 symbol_info_list call_stack::get_symbol_info (void) 855 {
860 { 856 return m_cs[m_curr_frame]->regexp_symbol_info (pattern);
861 return m_cs[m_curr_frame]->get_symbol_info (); 857 }
862 } 858
863 859 symbol_info_list call_stack::get_symbol_info (void)
864 symbol_info_list call_stack::top_scope_symbol_info (void) const 860 {
865 { 861 return m_cs[m_curr_frame]->get_symbol_info ();
866 return m_cs[0]->get_symbol_info (); 862 }
867 } 863
868 864 symbol_info_list call_stack::top_scope_symbol_info (void) const
869 octave_value call_stack::max_stack_depth (const octave_value_list& args, 865 {
870 int nargout) 866 return m_cs[0]->get_symbol_info ();
871 { 867 }
872 return set_internal_variable (m_max_stack_depth, args, nargout, 868
873 "max_stack_depth", 0); 869 octave_value call_stack::max_stack_depth (const octave_value_list& args,
874 } 870 int nargout)
875 871 {
876 void call_stack::make_persistent (const symbol_record& sym) 872 return set_internal_variable (m_max_stack_depth, args, nargout,
877 { 873 "max_stack_depth", 0);
878 m_cs[m_curr_frame]->make_persistent (sym); 874 }
879 } 875
880 876 void call_stack::make_persistent (const symbol_record& sym)
881 void call_stack::make_global (const symbol_record& sym) 877 {
882 { 878 m_cs[m_curr_frame]->make_persistent (sym);
883 m_cs[m_curr_frame]->make_global (sym); 879 }
884 } 880
885 881 void call_stack::make_global (const symbol_record& sym)
886 octave_value call_stack::global_varval (const std::string& name) const 882 {
887 { 883 m_cs[m_curr_frame]->make_global (sym);
888 auto p = m_global_values.find (name); 884 }
889 885
890 return p == m_global_values.end () ? octave_value () : p->second; 886 octave_value call_stack::global_varval (const std::string& name) const
891 } 887 {
892 888 auto p = m_global_values.find (name);
893 octave_value& call_stack::global_varref (const std::string& name) 889
894 { 890 return p == m_global_values.end () ? octave_value () : p->second;
895 return m_global_values[name]; 891 }
896 } 892
897 893 octave_value& call_stack::global_varref (const std::string& name)
898 octave_value call_stack::get_top_level_value (const std::string& name) const 894 {
899 { 895 return m_global_values[name];
900 return m_cs[0]->varval (name); 896 }
901 } 897
902 898 octave_value call_stack::get_top_level_value (const std::string& name) const
903 void call_stack::set_top_level_value (const std::string& name, 899 {
904 const octave_value& value) 900 return m_cs[0]->varval (name);
905 { 901 }
906 m_cs[0]->assign (name, value); 902
907 } 903 void call_stack::set_top_level_value (const std::string& name,
908 904 const octave_value& value)
909 octave_value call_stack::do_who (int argc, const string_vector& argv, 905 {
910 bool return_list, bool verbose) 906 m_cs[0]->assign (name, value);
911 { 907 }
912 octave_value retval; 908
913 909 octave_value call_stack::do_who (int argc, const string_vector& argv,
914 std::string my_name = argv[0]; 910 bool return_list, bool verbose)
915 911 {
916 std::string file_name; 912 octave_value retval;
917 913
918 bool from_file = false; 914 std::string my_name = argv[0];
919 bool global_only = false; 915
920 bool have_regexp = false; 916 std::string file_name;
921 917
922 int i = 1; 918 bool from_file = false;
923 while (i < argc) 919 bool global_only = false;
924 { 920 bool have_regexp = false;
925 if (argv[i] == "-file") 921
926 { 922 int i = 1;
927 if (from_file) 923 while (i < argc)
928 error ("%s: -file option may only be specified once", 924 {
929 my_name.c_str ()); 925 if (argv[i] == "-file")
930 926 {
931 from_file = true; 927 if (from_file)
932 928 error ("%s: -file option may only be specified once",
933 if (i == argc - 1) 929 my_name.c_str ());
934 error ("%s: -file argument must be followed by a filename", 930
935 my_name.c_str ()); 931 from_file = true;
936 932
937 file_name = argv[++i]; 933 if (i == argc - 1)
938 } 934 error ("%s: -file argument must be followed by a filename",
939 else if (argv[i] == "-regexp") 935 my_name.c_str ());
940 { 936
941 have_regexp = true; 937 file_name = argv[++i];
942 } 938 }
943 else if (argv[i] == "global") 939 else if (argv[i] == "-regexp")
944 global_only = true; 940 {
945 else if (argv[i][0] == '-') 941 have_regexp = true;
946 warning ("%s: unrecognized option '%s'", my_name.c_str (), 942 }
947 argv[i].c_str ()); 943 else if (argv[i] == "global")
948 else 944 global_only = true;
949 break; 945 else if (argv[i][0] == '-')
950 946 warning ("%s: unrecognized option '%s'", my_name.c_str (),
951 i++; 947 argv[i].c_str ());
952 } 948 else
953 949 break;
954 int npatterns = argc - i; 950
955 string_vector patterns; 951 i++;
956 if (npatterns > 0) 952 }
957 { 953
958 patterns.resize (npatterns); 954 int npatterns = argc - i;
959 for (int j = 0; j < npatterns; j++) 955 string_vector patterns;
960 patterns[j] = argv[i+j]; 956 if (npatterns > 0)
961 } 957 {
962 else 958 patterns.resize (npatterns);
963 { 959 for (int j = 0; j < npatterns; j++)
964 patterns.resize (1); 960 patterns[j] = argv[i+j];
965 patterns[0] = "*"; 961 }
966 } 962 else
967 963 {
968 if (from_file) 964 patterns.resize (1);
969 { 965 patterns[0] = "*";
970 // FIXME: This is an inefficient manner to implement this as the 966 }
971 // variables are loaded in to a temporary context and then treated. 967
972 // It would be better to refactor symbol_info_list to not store the 968 if (from_file)
973 // symbol records and then use it in load-save.cc (do_load) to 969 {
974 // implement this option there so that the variables are never 970 // FIXME: This is an inefficient manner to implement this as the
975 // stored at all. 971 // variables are loaded in to a temporary context and then treated.
976 972 // It would be better to refactor symbol_info_list to not store the
977 // Set up temporary scope. 973 // symbol records and then use it in load-save.cc (do_load) to
978 974 // implement this option there so that the variables are never
979 symbol_scope tmp_scope ("$dummy_scope$"); 975 // stored at all.
980 976
981 push (tmp_scope); 977 // Set up temporary scope.
982 978
983 unwind_action restore_scope ([=] (void) { pop (); }); 979 symbol_scope tmp_scope ("$dummy_scope$");
984 980
985 feval ("load", octave_value (file_name), 0); 981 push (tmp_scope);
986 982
987 std::string newmsg = "Variables in the file " + file_name + ":\n\n"; 983 unwind_action restore_scope ([=] (void) { pop (); });
988 984
989 if (global_only) 985 feval ("load", octave_value (file_name), 0);
990 return do_global_who_two (patterns, have_regexp, return_list, 986
991 verbose, newmsg); 987 std::string newmsg = "Variables in the file " + file_name + ":\n\n";
992 else 988
993 return do_who_two (patterns, have_regexp, return_list, verbose, 989 if (global_only)
994 newmsg); 990 return do_global_who_two (patterns, have_regexp, return_list,
995 } 991 verbose, newmsg);
996 else 992 else
997 { 993 return do_who_two (patterns, have_regexp, return_list, verbose,
998 if (global_only) 994 newmsg);
999 return do_global_who_two (patterns, have_regexp, return_list, 995 }
1000 verbose); 996 else
1001 else 997 {
1002 return do_who_two (patterns, have_regexp, return_list, verbose); 998 if (global_only)
1003 } 999 return do_global_who_two (patterns, have_regexp, return_list,
1004 } 1000 verbose);
1005 1001 else
1006 octave_value call_stack::do_who_two (const string_vector& patterns, 1002 return do_who_two (patterns, have_regexp, return_list, verbose);
1007 bool have_regexp, bool return_list, 1003 }
1008 bool verbose, const std::string& msg) 1004 }
1009 { 1005
1010 return m_cs[m_curr_frame]->who (patterns, have_regexp, return_list, 1006 octave_value call_stack::do_who_two (const string_vector& patterns,
1011 verbose, m_evaluator.whos_line_format (), 1007 bool have_regexp, bool return_list,
1012 msg); 1008 bool verbose, const std::string& msg)
1013 } 1009 {
1014 1010 return m_cs[m_curr_frame]->who (patterns, have_regexp, return_list,
1015 octave_value call_stack::do_global_who_two (const string_vector& patterns, 1011 verbose, m_evaluator.whos_line_format (),
1016 bool have_regexp, 1012 msg);
1017 bool return_list, bool verbose, 1013 }
1018 const std::string& msg) 1014
1019 { 1015 octave_value call_stack::do_global_who_two (const string_vector& patterns,
1020 symbol_info_list symbol_stats; 1016 bool have_regexp,
1021 std::list<std::string> symbol_names; 1017 bool return_list, bool verbose,
1022 1018 const std::string& msg)
1023 octave_idx_type npatterns = patterns.numel (); 1019 {
1024 1020 symbol_info_list symbol_stats;
1025 for (octave_idx_type j = 0; j < npatterns; j++) 1021 std::list<std::string> symbol_names;
1026 { 1022
1027 std::string pattern = patterns[j]; 1023 octave_idx_type npatterns = patterns.numel ();
1028 1024
1029 std::list<std::string> tmp; 1025 for (octave_idx_type j = 0; j < npatterns; j++)
1030 1026 {
1031 if (have_regexp) 1027 std::string pattern = patterns[j];
1032 { 1028
1033 regexp pat (pattern); 1029 std::list<std::string> tmp;
1034 1030
1035 for (auto& nm_ov : m_global_values) 1031 if (have_regexp)
1036 { 1032 {
1037 if (pat.is_match (nm_ov.first)) 1033 regexp pat (pattern);
1038 tmp.push_back (nm_ov.first); 1034
1039 } 1035 for (auto& nm_ov : m_global_values)
1040 } 1036 {
1041 else 1037 if (pat.is_match (nm_ov.first))
1042 { 1038 tmp.push_back (nm_ov.first);
1043 glob_match pat (pattern); 1039 }
1044 1040 }
1045 for (auto& nm_ov : m_global_values) 1041 else
1046 { 1042 {
1047 if (pat.match (nm_ov.first)) 1043 glob_match pat (pattern);
1048 tmp.push_back (nm_ov.first); 1044
1049 } 1045 for (auto& nm_ov : m_global_values)
1050 } 1046 {
1051 1047 if (pat.match (nm_ov.first))
1052 for (const auto& nm : tmp) 1048 tmp.push_back (nm_ov.first);
1053 { 1049 }
1054 octave_value value = m_global_values[nm]; 1050 }
1055 1051
1056 if (value.is_defined ()) 1052 for (const auto& nm : tmp)
1057 { 1053 {
1058 if (verbose) 1054 octave_value value = m_global_values[nm];
1059 { 1055
1060 bool is_formal = false; 1056 if (value.is_defined ())
1061 bool is_global = true; 1057 {
1062 bool is_persistent = false; 1058 if (verbose)
1063 1059 {
1064 symbol_info syminf (nm, value, is_formal, is_global, 1060 bool is_formal = false;
1065 is_persistent); 1061 bool is_global = true;
1066 1062 bool is_persistent = false;
1067 symbol_stats.append (syminf); 1063
1068 } 1064 symbol_info syminf (nm, value, is_formal, is_global,
1069 else 1065 is_persistent);
1070 symbol_names.push_back (nm); 1066
1071 } 1067 symbol_stats.append (syminf);
1072 } 1068 }
1073 } 1069 else
1074 1070 symbol_names.push_back (nm);
1075 if (return_list) 1071 }
1076 { 1072 }
1077 if (verbose) 1073 }
1078 { 1074
1079 std::string caller_fcn_name; 1075 if (return_list)
1080 octave_function *caller_fcn = caller_function (); 1076 {
1081 if (caller_fcn) 1077 if (verbose)
1082 caller_fcn_name = caller_fcn->name (); 1078 {
1083 1079 std::string caller_fcn_name;
1084 return symbol_stats.map_value (caller_fcn_name, 1); 1080 octave_function *caller_fcn = caller_function ();
1085 } 1081 if (caller_fcn)
1086 else 1082 caller_fcn_name = caller_fcn->name ();
1087 return Cell (string_vector (symbol_names)); 1083
1088 } 1084 return symbol_stats.map_value (caller_fcn_name, 1);
1089 else if (! (symbol_stats.empty () && symbol_names.empty ())) 1085 }
1090 { 1086 else
1091 if (msg.empty ()) 1087 return Cell (string_vector (symbol_names));
1092 octave_stdout << "Global variables:\n\n"; 1088 }
1093 else 1089 else if (! (symbol_stats.empty () && symbol_names.empty ()))
1094 octave_stdout << msg; 1090 {
1095 1091 if (msg.empty ())
1096 if (verbose) 1092 octave_stdout << "Global variables:\n\n";
1097 symbol_stats.display (octave_stdout, 1093 else
1098 m_evaluator.whos_line_format ()); 1094 octave_stdout << msg;
1099 else 1095
1100 { 1096 if (verbose)
1101 string_vector names (symbol_names); 1097 symbol_stats.display (octave_stdout,
1102 1098 m_evaluator.whos_line_format ());
1103 names.list_in_columns (octave_stdout); 1099 else
1104 } 1100 {
1105 1101 string_vector names (symbol_names);
1106 octave_stdout << "\n"; 1102
1107 } 1103 names.list_in_columns (octave_stdout);
1108 1104 }
1109 return octave_value (); 1105
1110 } 1106 octave_stdout << "\n";
1111 1107 }
1112 void call_stack::display (void) const 1108
1113 { 1109 return octave_value ();
1114 std::ostream& os = octave_stdout; 1110 }
1115 1111
1116 std::size_t nframes = size (); 1112 void call_stack::display (void) const
1117 1113 {
1118 for (std::size_t i = 0; i < nframes; i++) 1114 std::ostream& os = octave_stdout;
1119 { 1115
1120 m_cs[i]->display (false); 1116 std::size_t nframes = size ();
1121 if (i < nframes - 1) 1117
1122 os << std::endl; 1118 for (std::size_t i = 0; i < nframes; i++)
1123 } 1119 {
1124 } 1120 m_cs[i]->display (false);
1125 1121 if (i < nframes - 1)
1126 void call_stack::set_auto_fcn_var (stack_frame::auto_var_type avt, 1122 os << std::endl;
1127 const octave_value& val) 1123 }
1128 { 1124 }
1129 m_cs[m_curr_frame]->set_auto_fcn_var (avt, val); 1125
1130 } 1126 void call_stack::set_auto_fcn_var (stack_frame::auto_var_type avt,
1131 1127 const octave_value& val)
1132 octave_value call_stack::get_auto_fcn_var (stack_frame::auto_var_type avt) const 1128 {
1133 { 1129 m_cs[m_curr_frame]->set_auto_fcn_var (avt, val);
1134 return m_cs[m_curr_frame]->get_auto_fcn_var (avt); 1130 }
1135 } 1131
1132 octave_value call_stack::get_auto_fcn_var (stack_frame::auto_var_type avt) const
1133 {
1134 return m_cs[m_curr_frame]->get_auto_fcn_var (avt);
1135 }
1136 1136
1137 DEFMETHOD (max_stack_depth, interp, args, nargout, 1137 DEFMETHOD (max_stack_depth, interp, args, nargout,
1138 doc: /* -*- texinfo -*- 1138 doc: /* -*- texinfo -*-
1139 @deftypefn {} {@var{val} =} max_stack_depth () 1139 @deftypefn {} {@var{val} =} max_stack_depth ()
1140 @deftypefnx {} {@var{old_val} =} max_stack_depth (@var{new_val}) 1140 @deftypefnx {} {@var{old_val} =} max_stack_depth (@var{new_val})