GNU Octave  6.2.0
A high-level interpreted language, primarily intended for numerical computations, mostly compatible with Matlab
call-stack.cc
Go to the documentation of this file.
1 ////////////////////////////////////////////////////////////////////////
2 //
3 // Copyright (C) 1995-2021 The Octave Project Developers
4 //
5 // See the file COPYRIGHT.md in the top-level directory of this
6 // distribution or <https://octave.org/copyright/>.
7 //
8 // This file is part of Octave.
9 //
10 // Octave is free software: you can redistribute it and/or modify it
11 // under the terms of the GNU General Public License as published by
12 // the Free Software Foundation, either version 3 of the License, or
13 // (at your option) any later version.
14 //
15 // Octave is distributed in the hope that it will be useful, but
16 // WITHOUT ANY WARRANTY; without even the implied warranty of
17 // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
18 // GNU General Public License for more details.
19 //
20 // You should have received a copy of the GNU General Public License
21 // along with Octave; see the file COPYING. If not, see
22 // <https://www.gnu.org/licenses/>.
23 //
24 ////////////////////////////////////////////////////////////////////////
25 
26 #if defined (HAVE_CONFIG_H)
27 # include "config.h"
28 #endif
29 
30 #include "lo-regexp.h"
31 #include "str-vec.h"
32 
33 #include "call-stack.h"
34 #include "defun.h"
35 #include "interpreter.h"
36 #include "interpreter-private.h"
37 #include "oct-map.h"
38 #include "ov.h"
39 #include "ov-fcn.h"
40 #include "ov-fcn-handle.h"
41 #include "ov-usr-fcn.h"
42 #include "pager.h"
43 #include "parse.h"
44 #include "stack-frame.h"
45 #include "syminfo.h"
46 #include "symrec.h"
47 #include "symscope.h"
48 #include "variables.h"
49 
50 namespace octave
51 {
52  // Use static fields for the best efficiency.
53  // NOTE: C++0x will allow these two to be merged into one.
54  static const char *bt_fieldnames[] =
55  { "file", "name", "line", "column", nullptr };
56 
58 
60  : m_evaluator (evaluator), m_cs (), m_curr_frame (0),
61  m_max_stack_depth (1024), m_global_values ()
62  {
63  push (symbol_scope ("top scope"));
64  }
65 
67  {
68  if (m_cs.empty ())
69  error ("current_function: call stack is empty");
70 
71  octave_function *fcn = nullptr;
72 
73  size_t idx = m_curr_frame;
74 
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 
85  --idx;
86  }
87 
88  return fcn;
89  }
90 
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 
118  {
119  // Start at current frame.
120 
121  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 
137  {
138  // Start at current frame.
139 
140  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 
161  {
162  // Start at current frame.
163 
164  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 
185  {
186  // Start at current frame.
187 
188  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 
204  {
205  octave_user_code *retval = nullptr;
206 
207  // This should never happen...
208  if (m_curr_frame == 0)
209  return retval;
210 
211  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);
222  break;
223  }
224  }
225 
226  return retval;
227  }
228 
230  {
231  int retval = -1;
232 
233  // This should never happen...
234  if (m_curr_frame == 0)
235  return retval;
236 
237  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 
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  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 
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 
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 
349  (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  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<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  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 
396  const std::shared_ptr<stack_frame>& closure_frames)
397  {
398  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 
415  const stack_frame::local_vars_map& local_vars)
416  {
417  size_t new_frame_idx;
418  std::shared_ptr<stack_frame> parent_link;
419  std::shared_ptr<stack_frame> static_link;
420 
421  get_new_frame_index_and_links (new_frame_idx, parent_link, static_link);
422 
423  std::shared_ptr<stack_frame>
424  new_frame (stack_frame::create (m_evaluator, fcn, new_frame_idx,
425  parent_link, static_link, local_vars));
426 
427  m_cs.push_back (new_frame);
428 
429  m_curr_frame = new_frame_idx;
430  }
431 
433  {
434  size_t new_frame_idx;
435  std::shared_ptr<stack_frame> parent_link;
436  std::shared_ptr<stack_frame> static_link;
437 
438  get_new_frame_index_and_links (new_frame_idx, parent_link, static_link);
439 
440  std::shared_ptr<stack_frame>
441  new_frame (stack_frame::create (m_evaluator, script, new_frame_idx,
442  parent_link, static_link));
443 
444  m_cs.push_back (new_frame);
445 
446  m_curr_frame = new_frame_idx;
447  }
448 
450  {
451  size_t new_frame_idx;
452  std::shared_ptr<stack_frame> parent_link;
453  std::shared_ptr<stack_frame> static_link;
454 
455  get_new_frame_index_and_links (new_frame_idx, parent_link, static_link);
456 
457  std::shared_ptr<stack_frame>
458  new_frame (stack_frame::create (m_evaluator, fcn, new_frame_idx,
459  parent_link, static_link));
460 
461  m_cs.push_back (new_frame);
462 
463  m_curr_frame = new_frame_idx;
464  }
465 
466  bool call_stack::goto_frame (size_t n, bool verbose)
467  {
468  bool retval = false;
469 
470  if (n < m_cs.size ())
471  {
472  retval = true;
473 
474  m_curr_frame = n;
475 
476  if (verbose)
477  {
478  const std::shared_ptr<stack_frame> elt = m_cs[n];
479 
480  elt->display_stopped_in_message (octave_stdout);
481  }
482  }
483 
484  return retval;
485  }
486 
488  {
489  size_t user_frame = m_curr_frame;
490 
491  std::shared_ptr<stack_frame> frm = m_cs[user_frame];
492 
493  if (! (frm->is_user_fcn_frame () || frm->is_user_script_frame ()
494  || frm->is_scope_frame ()))
495  {
496  frm = frm->static_link ();
497 
498  user_frame = frm->index ();
499  }
500 
501  return user_frame;
502  }
503 
504  std::shared_ptr<stack_frame> call_stack::current_user_frame (void) const
505  {
506  size_t frame = find_current_user_frame ();
507 
508  return m_cs[frame];
509  }
510 
511  // Go to the Nth frame (up if N is negative or down if positive) in
512  // the call stack that corresponds to a script, function, or scope
513  // beginning with the frame indexed by START.
514 
515  size_t call_stack::dbupdown (size_t start, int n, bool verbose)
516  {
517  if (start >= m_cs.size ())
518  error ("invalid stack frame");
519 
520  // Can't go up from here.
521 
522  if (start == 0 && n < 0)
523  {
524  if (verbose)
525  m_cs[start]->display_stopped_in_message (octave_stdout);
526 
527  return start;
528  }
529 
530  std::shared_ptr<stack_frame> frm = m_cs[start];
531 
532  if (! (frm && (frm->is_user_fcn_frame ()
533  || frm->is_user_script_frame ()
534  || frm->is_scope_frame ())))
535  error ("call_stack::dbupdown: invalid initial frame in call stack!");
536 
537  // Use index into the call stack to begin the search. At this point
538  // we iterate up or down using indexing instead of static links
539  // because ... FIXME: it's a bit complicated, but deserves
540  // explanation. May be easiest with some pictures of the call stack
541  // for an example or two.
542 
543  size_t xframe = frm->index ();
544 
545  if (n == 0)
546  {
547  if (verbose)
548  frm->display_stopped_in_message (octave_stdout);
549 
550  return xframe;
551  }
552 
553  int incr = 0;
554 
555  if (n < 0)
556  {
557  incr = -1;
558  n = -n;
559  }
560  else if (n > 0)
561  incr = 1;
562 
563  size_t last_good_frame = 0;
564 
565  while (true)
566  {
567  frm = m_cs[xframe];
568 
569  if (frm->is_user_fcn_frame () || frm->is_user_script_frame ()
570  || frm->is_scope_frame ())
571  {
572  last_good_frame = xframe;
573 
574  if (n == 0)
575  break;
576 
577  n--;
578  }
579 
580  xframe += incr;
581 
582  if (xframe == 0)
583  {
584  last_good_frame = 0;
585  break;
586  }
587 
588  if (xframe == m_cs.size ())
589  break;
590  }
591 
592  if (verbose)
593  m_cs[last_good_frame]->display_stopped_in_message (octave_stdout);
594 
595  return last_good_frame;
596  }
597 
598  // Like dbupdown above but find the starting frame automatically from
599  // the current frame. If the current frame is already a user
600  // function, script, or scope frame, use that. Otherwise, follow
601  // the static link for the current frame. If that is not a user
602  // function, script or scope frame then there is an error in the
603  // implementation.
604 
605  size_t call_stack::dbupdown (int n, bool verbose)
606  {
607  size_t start = find_current_user_frame ();
608 
609  return dbupdown (start, n, verbose);
610  }
611 
612  // May be used to temporarily change the value ov m_curr_frame inside
613  // a function like evalin. If used in a function like dbup, the new
614  // value of m_curr_frame would be wiped out when dbup returns and the
615  // stack frame for dbup is popped.
616 
618  {
619  size_t start = find_current_user_frame ();
620 
621  std::shared_ptr<stack_frame> caller_frame = m_cs[start]->static_link ();
622 
623  // Allow evalin ('caller', ...) to work when called from the
624  // top-level prompt.
625 
626  m_curr_frame = caller_frame ? caller_frame->index () : 0;
627  }
628 
630  {
631  if (m_curr_frame > 0)
632  m_curr_frame = 0;
633  }
634 
635  std::list<std::shared_ptr<stack_frame>>
637  {
638  std::list<std::shared_ptr<stack_frame>> frames;
639 
640  // curr_frame is the index to the current frame in the overall call
641  // stack, which includes any compiled function frames and scope
642  // frames. The curr_user_frame value we set is the index into the
643  // subset of frames returned in the octave_map object.
644 
645  size_t curr_frame = find_current_user_frame ();
646 
647  // Don't include top-level stack frame in the list.
648 
649  for (size_t n = m_cs.size () - 1; n > 0; n--)
650  {
651  std::shared_ptr<stack_frame> frm = m_cs[n];
652 
653  if (frm->is_user_script_frame () || frm->is_user_fcn_frame ()
654  || frm->is_scope_frame ())
655  {
656  if (frm->index () == curr_frame)
657  curr_user_frame = frames.size ();
658 
659  frames.push_back (frm);
660  }
661 
662  if (n == 0)
663  break;
664  }
665 
666  return frames;
667  }
668 
669  std::list<std::shared_ptr<stack_frame>>
671  {
672  octave_idx_type curr_user_frame = -1;
673 
674  return backtrace_frames (curr_user_frame);
675  }
676 
677  std::list<frame_info>
679  bool print_subfn) const
680  {
681  std::list<std::shared_ptr<stack_frame>> frames
682  = backtrace_frames (curr_user_frame);
683 
684  std::list<frame_info> retval;
685 
686  for (const auto& frm : frames)
687  {
688  if (frm->is_user_script_frame () || frm->is_user_fcn_frame ()
689  || frm->is_scope_frame ())
690  {
691  retval.push_back (frame_info (frm->fcn_file_name (),
692  frm->fcn_name (print_subfn),
693  frm->line (), frm->column ()));
694  }
695  }
696 
697  return retval;
698  }
699 
700  std::list<frame_info> call_stack::backtrace_info (void) const
701  {
702  octave_idx_type curr_user_frame = -1;
703 
704  return backtrace_info (curr_user_frame, true);
705  }
706 
708  bool print_subfn) const
709  {
710  std::list<std::shared_ptr<stack_frame>> frames
711  = backtrace_frames (curr_user_frame);
712 
713  size_t nframes = frames.size ();
714 
715  octave_map retval (dim_vector (nframes, 1), bt_fields);
716 
717  Cell& file = retval.contents (0);
718  Cell& name = retval.contents (1);
719  Cell& line = retval.contents (2);
720  Cell& column = retval.contents (3);
721 
722  octave_idx_type k = 0;
723 
724  for (const auto& frm : frames)
725  {
726  if (frm->is_user_script_frame () || frm->is_user_fcn_frame ()
727  || frm->is_scope_frame ())
728  {
729  file(k) = frm->fcn_file_name ();
730  name(k) = frm->fcn_name (print_subfn);
731  line(k) = frm->line ();
732  column(k) = frm->column ();
733 
734  k++;
735  }
736  }
737 
738  return retval;
739  }
740 
742  {
743  octave_idx_type curr_user_frame = -1;
744 
745  return backtrace (curr_user_frame, true);
746  }
747 
749  {
750  return octave_map (dim_vector (0, 1), bt_fields);
751  }
752 
753  void call_stack::pop (void)
754  {
755  // Never pop top scope.
756  // FIXME: is it possible for this case to happen?
757 
758  if (m_cs.size () > 1)
759  {
760  std::shared_ptr<stack_frame> elt = m_cs.back ();
761 
762  std::shared_ptr<stack_frame> caller = elt->parent_link ();
763 
764  m_curr_frame = caller->index ();
765 
766  m_cs.pop_back ();
767  }
768  }
769 
770  void call_stack::clear (void)
771  {
772  while (! m_cs.empty ())
773  pop ();
774  }
775 
777  {
778  return m_cs[m_curr_frame]->all_variables ();
779  }
780 
781  std::list<std::string> call_stack::global_variable_names (void) const
782  {
783  std::list<std::string> retval;
784 
785  for (const auto& nm_ov : m_global_values)
786  {
787  if (nm_ov.second.is_defined ())
788  retval.push_back (nm_ov.first);
789  }
790 
791  retval.sort ();
792 
793  return retval;
794  }
795 
796  std::list<std::string> call_stack::top_level_variable_names (void) const
797  {
798  return m_cs[0]->variable_names ();
799  }
800 
801  std::list<std::string> call_stack::variable_names (void) const
802  {
803  return m_cs[m_curr_frame]->variable_names ();
804  }
805 
806  void call_stack::clear_global_variable (const std::string& name)
807  {
808  auto p = m_global_values.find (name);
809 
810  if (p != m_global_values.end ())
811  p->second = octave_value ();
812  }
813 
814  void call_stack::clear_global_variable_pattern (const std::string& pattern)
815  {
816  glob_match pat (pattern);
817 
818  for (auto& nm_ov : m_global_values)
819  {
820  if (pat.match (nm_ov.first))
821  nm_ov.second = octave_value ();
822  }
823  }
824 
825  void call_stack::clear_global_variable_regexp (const std::string& pattern)
826  {
827  octave::regexp pat (pattern);
828 
829  for (auto& nm_ov : m_global_values)
830  {
831  if (pat.is_match (nm_ov.first))
832  nm_ov.second = octave_value ();
833  }
834  }
835 
837  {
838  for (auto& nm_ov : m_global_values)
839  nm_ov.second = octave_value ();
840  }
841 
843  call_stack::glob_symbol_info (const std::string& pattern) const
844  {
845  return m_cs[m_curr_frame]->glob_symbol_info (pattern);
846  }
847 
849  call_stack::regexp_symbol_info (const std::string& pattern) const
850  {
851  return m_cs[m_curr_frame]->regexp_symbol_info (pattern);
852  }
853 
855  {
856  return m_cs[m_curr_frame]->get_symbol_info ();
857  }
858 
860  {
861  return m_cs[0]->get_symbol_info ();
862  }
863 
865  int nargout)
866  {
867  return set_internal_variable (m_max_stack_depth, args, nargout,
868  "max_stack_depth", 0);
869  }
870 
872  {
873  m_cs[m_curr_frame]->make_persistent (sym);
874  }
875 
877  {
878  m_cs[m_curr_frame]->make_global (sym);
879  }
880 
881  octave_value call_stack::global_varval (const std::string& name) const
882  {
883  auto p = m_global_values.find (name);
884 
885  return p == m_global_values.end () ? octave_value () : p->second;
886  }
887 
889  {
890  return m_global_values[name];
891  }
892 
894  {
895  return m_cs[0]->varval (name);
896  }
897 
898  void call_stack::set_top_level_value (const std::string& name,
899  const octave_value& value)
900  {
901  m_cs[0]->assign (name, value);
902  }
903 
905  bool return_list, bool verbose)
906  {
908 
909  std::string my_name = argv[0];
910 
911  std::string file_name;
912 
913  bool from_file = false;
914  bool global_only = false;
915  bool have_regexp = false;
916 
917  int i = 1;
918  while (i < argc)
919  {
920  if (argv[i] == "-file")
921  {
922  if (from_file)
923  error ("%s: -file option may only be specified once",
924  my_name.c_str ());
925 
926  from_file = true;
927 
928  if (i == argc - 1)
929  error ("%s: -file argument must be followed by a filename",
930  my_name.c_str ());
931 
932  file_name = argv[++i];
933  }
934  else if (argv[i] == "-regexp")
935  {
936  have_regexp = true;
937  }
938  else if (argv[i] == "global")
939  global_only = true;
940  else if (argv[i][0] == '-')
941  warning ("%s: unrecognized option '%s'", my_name.c_str (),
942  argv[i].c_str ());
943  else
944  break;
945 
946  i++;
947  }
948 
949  int npatterns = argc - i;
950  string_vector patterns;
951  if (npatterns > 0)
952  {
953  patterns.resize (npatterns);
954  for (int j = 0; j < npatterns; j++)
955  patterns[j] = argv[i+j];
956  }
957  else
958  {
959  patterns.resize (1);
960  patterns[0] = "*";
961  }
962 
963  if (from_file)
964  {
965  // FIXME: This is an inefficient manner to implement this as the
966  // variables are loaded in to a temporary context and then treated.
967  // It would be better to refactor symbol_info_list to not store the
968  // symbol records and then use it in load-save.cc (do_load) to
969  // implement this option there so that the variables are never
970  // stored at all.
971 
972  unwind_protect frame;
973 
974  // Set up temporary scope.
975 
976  symbol_scope tmp_scope ("$dummy_scope$");
977 
978  push (tmp_scope);
979  frame.add_method (*this, &call_stack::pop);
980 
981  feval ("load", octave_value (file_name), 0);
982 
983  std::string newmsg = "Variables in the file " + file_name + ":\n\n";
984 
985  if (global_only)
986  return do_global_who_two (patterns, have_regexp, return_list,
987  verbose, newmsg);
988  else
989  return do_who_two (patterns, have_regexp, return_list, verbose,
990  newmsg);
991  }
992  else
993  {
994  if (global_only)
995  return do_global_who_two (patterns, have_regexp, return_list,
996  verbose);
997  else
998  return do_who_two (patterns, have_regexp, return_list, verbose);
999  }
1000  }
1001 
1003  bool have_regexp, bool return_list,
1004  bool verbose, const std::string& msg)
1005  {
1006  return m_cs[m_curr_frame]->who (patterns, have_regexp, return_list,
1007  verbose, m_evaluator.whos_line_format (),
1008  msg);
1009  }
1010 
1012  bool have_regexp,
1013  bool return_list, bool verbose,
1014  const std::string& msg)
1015  {
1016  symbol_info_list symbol_stats;
1017  std::list<std::string> symbol_names;
1018 
1019  octave_idx_type npatterns = patterns.numel ();
1020 
1021  for (octave_idx_type j = 0; j < npatterns; j++)
1022  {
1023  std::string pattern = patterns[j];
1024 
1025  std::list<std::string> tmp;
1026 
1027  if (have_regexp)
1028  {
1029  octave::regexp pat (pattern);
1030 
1031  for (auto& nm_ov : m_global_values)
1032  {
1033  if (pat.is_match (nm_ov.first))
1034  tmp.push_back (nm_ov.first);
1035  }
1036  }
1037  else
1038  {
1039  glob_match pat (pattern);
1040 
1041  for (auto& nm_ov : m_global_values)
1042  {
1043  if (pat.match (nm_ov.first))
1044  tmp.push_back (nm_ov.first);
1045  }
1046  }
1047 
1048  for (const auto& nm : tmp)
1049  {
1050  octave_value value = m_global_values[nm];
1051 
1052  if (value.is_defined ())
1053  {
1054  if (verbose)
1055  {
1056  bool is_formal = false;
1057  bool is_global = true;
1058  bool is_persistent = false;
1059 
1060  symbol_info syminf (nm, value, is_formal, is_global,
1061  is_persistent);
1062 
1063  symbol_stats.append (syminf);
1064  }
1065  else
1066  symbol_names.push_back (nm);
1067  }
1068  }
1069  }
1070 
1071  if (return_list)
1072  {
1073  if (verbose)
1074  {
1075  std::string caller_fcn_name;
1076  octave_function *caller_fcn = caller_function ();
1077  if (caller_fcn)
1078  caller_fcn_name = caller_fcn->name ();
1079 
1080  return symbol_stats.map_value (caller_fcn_name, 1);
1081  }
1082  else
1083  return Cell (string_vector (symbol_names));
1084  }
1085  else if (! (symbol_stats.empty () && symbol_names.empty ()))
1086  {
1087  if (msg.empty ())
1088  octave_stdout << "Global variables:\n\n";
1089  else
1090  octave_stdout << msg;
1091 
1092  if (verbose)
1093  symbol_stats.display (octave_stdout,
1095  else
1096  {
1097  string_vector names (symbol_names);
1098 
1100  }
1101 
1102  octave_stdout << "\n";
1103  }
1104 
1105  return octave_value ();
1106  }
1107 
1108  void call_stack::display (void) const
1109  {
1110  std::ostream& os = octave_stdout;
1111 
1112  size_t nframes = size ();
1113 
1114  for (size_t i = 0; i < nframes; i++)
1115  {
1116  m_cs[i]->display (false);
1117  if (i < nframes - 1)
1118  os << std::endl;
1119  }
1120  }
1121 
1123  const octave_value& val)
1124  {
1125  m_cs[m_curr_frame]->set_auto_fcn_var (avt, val);
1126  }
1127 
1129  {
1130  return m_cs[m_curr_frame]->get_auto_fcn_var (avt);
1131  }
1132 }
1133 
1134 DEFMETHOD (max_stack_depth, interp, args, nargout,
1135  doc: /* -*- texinfo -*-
1136 @deftypefn {} {@var{val} =} max_stack_depth ()
1137 @deftypefnx {} {@var{old_val} =} max_stack_depth (@var{new_val})
1138 @deftypefnx {} {} max_stack_depth (@var{new_val}, "local")
1139 Query or set the internal limit on the number of times a function may
1140 be called recursively.
1141 
1142 If the limit is exceeded, an error message is printed and control returns to
1143 the top level.
1144 
1145 When called from inside a function with the @qcode{"local"} option, the
1146 variable is changed locally for the function and any subroutines it calls.
1147 The original variable value is restored when exiting the function.
1148 
1149 @seealso{max_recursion_depth}
1150 @end deftypefn */)
1151 {
1152  octave::tree_evaluator& tw = interp.get_evaluator ();
1153 
1154  return tw.max_stack_depth (args, nargout);
1155 }
1156 
1157 /*
1158 %!test
1159 %! orig_val = max_stack_depth ();
1160 %! old_val = max_stack_depth (2*orig_val);
1161 %! assert (orig_val, old_val);
1162 %! assert (max_stack_depth (), 2*orig_val);
1163 %! max_stack_depth (orig_val);
1164 %! assert (max_stack_depth (), orig_val);
1165 
1166 %!error (max_stack_depth (1, 2))
1167 */
1168 
1169 DEFMETHOD (who, interp, args, nargout,
1170  doc: /* -*- texinfo -*-
1171 @deftypefn {} {} who
1172 @deftypefnx {} {} who pattern @dots{}
1173 @deftypefnx {} {} who option pattern @dots{}
1174 @deftypefnx {} {C =} who ("pattern", @dots{})
1175 List currently defined variables matching the given patterns.
1176 
1177 Valid pattern syntax is the same as described for the @code{clear} command.
1178 If no patterns are supplied, all variables are listed.
1179 
1180 By default, only variables visible in the local scope are displayed.
1181 
1182 The following are valid options, but may not be combined.
1183 
1184 @table @code
1185 @item global
1186 List variables in the global scope rather than the current scope.
1187 
1188 @item -regexp
1189 The patterns are considered to be regular expressions when matching the
1190 variables to display. The same pattern syntax accepted by the @code{regexp}
1191 function is used.
1192 
1193 @item -file
1194 The next argument is treated as a filename. All variables found within the
1195 specified file are listed. No patterns are accepted when reading variables
1196 from a file.
1197 @end table
1198 
1199 If called as a function, return a cell array of defined variable names
1200 matching the given patterns.
1201 @seealso{whos, isglobal, isvarname, exist, regexp}
1202 @end deftypefn */)
1203 {
1204  int argc = args.length () + 1;
1205 
1206  string_vector argv = args.make_argv ("who");
1207 
1208  octave::tree_evaluator& tw = interp.get_evaluator ();
1209 
1210  return tw.do_who (argc, argv, nargout == 1);
1211 }
1212 
1213 /*
1214 %!test
1215 %! avar = magic (4);
1216 %! ftmp = [tempname() ".mat"];
1217 %! save_default_options ("-binary", "local");
1218 %! unwind_protect
1219 %! save (ftmp, "avar");
1220 %! vars = whos ("-file", ftmp);
1221 %! assert (numel (vars), 1);
1222 %! assert (isstruct (vars));
1223 %! assert (vars.name, "avar");
1224 %! assert (vars.size, [4, 4]);
1225 %! assert (vars.class, "double");
1226 %! assert (vars.bytes, 128);
1227 %! unwind_protect_cleanup
1228 %! unlink (ftmp);
1229 %! end_unwind_protect
1230 */
1231 
1232 DEFMETHOD (whos, interp, args, nargout,
1233  doc: /* -*- texinfo -*-
1234 @deftypefn {} {} whos
1235 @deftypefnx {} {} whos pattern @dots{}
1236 @deftypefnx {} {} whos option pattern @dots{}
1237 @deftypefnx {} {S =} whos ("pattern", @dots{})
1238 Provide detailed information on currently defined variables matching the
1239 given patterns.
1240 
1241 Options and pattern syntax are the same as for the @code{who} command.
1242 
1243 Extended information about each variable is summarized in a table with the
1244 following default entries.
1245 
1246 @table @asis
1247 @item Attr
1248 Attributes of the listed variable. Possible attributes are:
1249 
1250 @table @asis
1251 @item blank
1252 Variable in local scope
1253 
1254 @item @code{c}
1255 Variable of complex type.
1256 
1257 @item @code{f}
1258 Formal parameter (function argument).
1259 
1260 @item @code{g}
1261 Variable with global scope.
1262 
1263 @item @code{p}
1264 Persistent variable.
1265 @end table
1266 
1267 @item Name
1268 The name of the variable.
1269 
1270 @item Size
1271 The logical size of the variable. A scalar is 1x1, a vector is
1272 @nospell{1xN} or @nospell{Nx1}, a 2-D matrix is @nospell{MxN}.
1273 
1274 @item Bytes
1275 The amount of memory currently used to store the variable.
1276 
1277 @item Class
1278 The class of the variable. Examples include double, single, char, uint16,
1279 cell, and struct.
1280 @end table
1281 
1282 The table can be customized to display more or less information through
1283 the function @code{whos_line_format}.
1284 
1285 If @code{whos} is called as a function, return a struct array of defined
1286 variable names matching the given patterns. Fields in the structure
1287 describing each variable are: name, size, bytes, class, global, sparse,
1288 complex, nesting, persistent.
1289 @seealso{who, whos_line_format}
1290 @end deftypefn */)
1291 {
1292  int argc = args.length () + 1;
1293 
1294  string_vector argv = args.make_argv ("whos");
1295 
1296  octave::tree_evaluator& tw = interp.get_evaluator ();
1297 
1298  return tw.do_who (argc, argv, nargout == 1, true);
1299 }
Array< T > sort(int dim=0, sortmode mode=ASCENDING) const
Size of the specified dimension.
Definition: Array.cc:1757
Array< T > column(octave_idx_type k) const
Extract column: A(:,k+1).
Definition: Array.cc:261
Definition: Cell.h:43
Cell column(octave_idx_type i) const
Definition: Cell.cc:303
Vector representing the dimensions (size) of an Array.
Definition: dim-vector.h:95
bool match(const std::string &str) const
Definition: glob-match.cc:35
line(const graphics_handle &mh, const graphics_handle &p)
Definition: graphics.in.h:4318
void add_method(T *obj, void(T::*method)(Params...), Args &&... args)
void append(const elt_type &s)
Definition: base-list.h:92
bool empty(void) const
Definition: base-list.h:50
size_t size(void) const
Definition: call-stack.h:89
symbol_info_list glob_symbol_info(const std::string &pattern) const
Definition: call-stack.cc:843
void clear_global_variables(void)
Definition: call-stack.cc:836
std::string get_dispatch_class(void) const
Definition: call-stack.cc:288
octave_value global_varval(const std::string &name) const
Definition: call-stack.cc:881
bool goto_frame(size_t n=0, bool verbose=false)
Definition: call-stack.cc:466
bool is_class_constructor_executing(std::string &dispatch_class) const
Definition: call-stack.cc:312
void clear(void)
Definition: call-stack.cc:770
void push(const symbol_scope &scope)
Definition: call-stack.cc:378
tree_evaluator & m_evaluator
Definition: call-stack.h:309
void get_new_frame_index_and_links(size_t &new_frame_idx, std::shared_ptr< stack_frame > &parent_link, std::shared_ptr< stack_frame > &static_link) const
Definition: call-stack.cc:349
octave_user_code * current_user_code(void) const
Definition: call-stack.cc:117
std::map< std::string, octave_value > m_global_values
Definition: call-stack.h:325
void goto_base_frame(void)
Definition: call-stack.cc:629
size_t dbupdown(size_t start, int n, bool verbose)
Definition: call-stack.cc:515
int current_user_code_line(void) const
Definition: call-stack.cc:136
void set_top_level_value(const std::string &name, const octave_value &value)
Definition: call-stack.cc:898
void make_persistent(const symbol_record &sym)
Definition: call-stack.cc:871
int current_line(void) const
Definition: call-stack.cc:91
bool all_scripts(void) const
Definition: call-stack.cc:326
std::list< std::string > global_variable_names(void) const
Definition: call-stack.cc:781
octave_value get_auto_fcn_var(stack_frame::auto_var_type avt) const
Definition: call-stack.cc:1128
std::list< std::string > top_level_variable_names(void) const
Definition: call-stack.cc:796
symbol_info_list top_scope_symbol_info(void) const
Definition: call-stack.cc:859
void set_dispatch_class(const std::string &class_name)
Definition: call-stack.cc:293
std::list< std::shared_ptr< stack_frame > > backtrace_frames(void) const
Definition: call-stack.cc:670
void goto_caller_frame(void)
Definition: call-stack.cc:617
symbol_info_list regexp_symbol_info(const std::string &pattern) const
Definition: call-stack.cc:849
void set_auto_fcn_var(stack_frame::auto_var_type avt, const octave_value &val)
Definition: call-stack.cc:1122
std::shared_ptr< stack_frame > current_user_frame(void) const
Definition: call-stack.cc:504
octave_value & global_varref(const std::string &name)
Definition: call-stack.cc:888
octave_user_code * debug_user_code(void) const
Definition: call-stack.cc:203
octave_map backtrace(void) const
Definition: call-stack.cc:741
void display(void) const
Definition: call-stack.cc:1108
void make_global(const symbol_record &sym)
Definition: call-stack.cc:876
unwind_protect * curr_fcn_unwind_protect_frame(void)
Definition: call-stack.cc:184
octave_value get_top_level_value(const std::string &name) const
Definition: call-stack.cc:893
octave_value do_global_who_two(const string_vector &patterns, bool have_regexp, bool return_list, bool verbose, const std::string &msg="")
Definition: call-stack.cc:1011
symbol_info_list get_symbol_info(void)
Definition: call-stack.cc:854
int current_user_code_column(void) const
Definition: call-stack.cc:160
octave_function * caller_function(void) const
Definition: call-stack.h:76
stack_frames m_cs
Definition: call-stack.h:312
octave_value do_who(int argc, const string_vector &argv, bool return_list, bool verbose=false)
Definition: call-stack.cc:904
bool is_class_method_executing(std::string &dispatch_class) const
Definition: call-stack.cc:298
octave_map empty_backtrace(void) const
Definition: call-stack.cc:748
call_stack(tree_evaluator &evaluator)
Definition: call-stack.cc:59
std::list< frame_info > backtrace_info(void) const
Definition: call-stack.cc:700
std::list< std::string > variable_names(void) const
Definition: call-stack.cc:801
void clear_global_variable(const std::string &name)
Definition: call-stack.cc:806
void clear_global_variable_regexp(const std::string &pattern)
Definition: call-stack.cc:825
octave_value max_stack_depth(const octave_value_list &args, int nargout)
Definition: call-stack.cc:864
void clear_global_variable_pattern(const std::string &pattern)
Definition: call-stack.cc:814
int debug_user_code_column(void) const
Definition: call-stack.cc:258
int debug_user_code_line(void) const
Definition: call-stack.cc:229
octave_function * current_function(bool skip_first=false) const
Definition: call-stack.cc:66
size_t find_current_user_frame(void) const
Definition: call-stack.cc:487
int current_column(void) const
Definition: call-stack.cc:104
octave_value do_who_two(const string_vector &patterns, bool have_regexp, bool return_list, bool verbose, const std::string &msg="")
Definition: call-stack.cc:1002
symbol_info_list all_variables(void)
Definition: call-stack.cc:776
bool is_match(const std::string &buffer)
Definition: lo-regexp.cc:440
static stack_frame * create(tree_evaluator &tw, octave_function *fcn, size_t index, const std::shared_ptr< stack_frame > &parent_link, const std::shared_ptr< stack_frame > &static_link)
std::map< std::string, octave_value > local_vars_map
Definition: stack-frame.h:112
octave_map map_value(const std::string &caller_function_name, int nesting_level) const
Definition: syminfo.cc:190
void display(std::ostream &os, const std::string &format) const
Definition: syminfo.cc:330
octave_value do_who(int argc, const string_vector &argv, bool return_list, bool verbose=false)
Definition: pt-eval.cc:3799
octave_value max_stack_depth(const octave_value_list &args, int nargout)
Definition: pt-eval.cc:2093
octave_value whos_line_format(const octave_value_list &args, int nargout)
Definition: pt-eval.cc:3744
virtual bool is_user_code(void) const
Definition: ov-base.h:473
std::string name(void) const
Definition: ov-fcn.h:214
bool is_defined(void) const
Definition: ov.h:551
void resize(octave_idx_type n, const std::string &rfv="")
Definition: str-vec.h:95
std::ostream & list_in_columns(std::ostream &, int width=0, const std::string &prefix="") const
Definition: str-vec.cc:201
octave_idx_type numel(void) const
Definition: str-vec.h:100
#define DEFMETHOD(name, interp_name, args_name, nargout_name, doc)
Macro to define a builtin method.
Definition: defun.h:138
void warning(const char *fmt,...)
Definition: error.cc:1050
void error(const char *fmt,...)
Definition: error.cc:968
QString name
octave_idx_type n
Definition: mx-inlines.cc:753
static const char * bt_fieldnames[]
Definition: call-stack.cc:54
static const octave_fields bt_fields(bt_fieldnames)
static double f(double k, double l_nu, double c_pm)
Definition: randpoisson.cc:118
octave_value_list feval(const char *name, const octave_value_list &args, int nargout)
Evaluate an Octave function (built-in or interpreted) and return the list of result values.
Definition: oct-parse.cc:9580
return octave_value(v1.char_array_value() . concat(v2.char_array_value(), ra_idx),((a1.is_sq_string()||a2.is_sq_string()) ? '\'' :'"'))
octave_value::octave_value(const Array< char > &chm, char type) return retval
Definition: ov.cc:811
#define octave_stdout
Definition: pager.h:313
octave_value set_internal_variable(bool &var, const octave_value_list &args, int nargout, const char *nm)
Definition: variables.cc:608