GNU Octave  4.4.1
A high-level interpreted language, primarily intended for numerical computations, mostly compatible with Matlab
variables.cc
Go to the documentation of this file.
1 /*
2 
3 Copyright (C) 1993-2018 John W. Eaton
4 Copyright (C) 2009-2010 VZLU Prague
5 
6 This file is part of Octave.
7 
8 Octave is free software: you can redistribute it and/or modify it
9 under the terms of the GNU General Public License as published by
10 the Free Software Foundation, either version 3 of the License, or
11 (at your option) any later version.
12 
13 Octave is distributed in the hope that it will be useful, but
14 WITHOUT ANY WARRANTY; without even the implied warranty of
15 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
16 GNU General Public License for more details.
17 
18 You should have received a copy of the GNU General Public License
19 along with Octave; see the file COPYING. If not, see
20 <https://www.gnu.org/licenses/>.
21 
22 */
23 
24 #if defined (HAVE_CONFIG_H)
25 # include "config.h"
26 #endif
27 
28 #include <cstdio>
29 #include <cstring>
30 
31 #include <iomanip>
32 #include <set>
33 #include <string>
34 
35 #include "file-stat.h"
36 #include "oct-env.h"
37 #include "file-ops.h"
38 #include "glob-match.h"
39 #include "lo-regexp.h"
40 #include "str-vec.h"
41 
42 #include "call-stack.h"
43 #include "defaults.h"
44 #include "Cell.h"
45 #include "defun.h"
46 #include "dirfns.h"
47 #include "error.h"
48 #include "errwarn.h"
49 #include "help.h"
50 #include "input.h"
51 #include "interpreter-private.h"
52 #include "interpreter.h"
53 #include "lex.h"
54 #include "load-path.h"
55 #include "octave-link.h"
57 #include "oct-map.h"
58 #include "ovl.h"
59 #include "ov.h"
60 #include "ov-class.h"
61 #include "ov-usr-fcn.h"
62 #include "pager.h"
63 #include "parse.h"
64 #include "symtab.h"
65 #include "unwind-prot.h"
66 #include "utils.h"
67 #include "variables.h"
68 
69 // Defines layout for the whos/who -long command
71  = " %a:4; %ln:6; %cs:16:6:1; %rb:12; %lc:-1;\n";
72 
73 // Attributes of variables and functions.
74 
75 // Is this octave_value a valid function?
76 
78 is_valid_function (const std::string& fcn_name,
79  const std::string& warn_for, bool warn)
80 {
81  octave_function *ans = nullptr;
82 
83  if (! fcn_name.empty ())
84  {
85  octave::symbol_table& symtab
86  = octave::__get_symbol_table__ ("is_valid_function");
87 
88  octave_value val = symtab.find_function (fcn_name);
89 
90  if (val.is_defined ())
91  ans = val.function_value (true);
92  }
93 
94  // FIXME: Should this be "err" and "error_for", rather than warn?
95  if (! ans && warn)
96  error ("%s: the symbol '%s' is not valid as a function",
97  warn_for.c_str (), fcn_name.c_str ());
98 
99  return ans;
100 }
101 
104  const std::string& warn_for, bool warn)
105 {
106  octave_function *ans = nullptr;
107 
108  std::string fcn_name;
109 
110  if (arg.is_string ())
111  {
112  fcn_name = arg.string_value ();
113 
114  ans = is_valid_function (fcn_name, warn_for, warn);
115  }
116  else if (warn)
117  // FIXME: Should this be "err" and "error_for", rather than warn?
118  error ("%s: argument must be a string containing function name",
119  warn_for.c_str ());
120 
121  return ans;
122 }
123 
125 extract_function (const octave_value& arg, const std::string& warn_for,
126  const std::string& fname, const std::string& header,
127  const std::string& trailer)
128 {
129  octave_function *retval = nullptr;
130 
131  retval = is_valid_function (arg, warn_for, 0);
132 
133  if (! retval)
134  {
135  std::string s = arg.xstring_value ("%s: argument must be a string",
136  warn_for.c_str ());
137 
138  std::string cmd = header;
139  cmd.append (s);
140  cmd.append (trailer);
141 
142  int parse_status;
143 
144  octave::eval_string (cmd, true, parse_status, 0);
145 
146  if (parse_status != 0)
147  error ("%s: '%s' is not valid as a function",
148  warn_for.c_str (), fname.c_str ());
149 
150  retval = is_valid_function (fname, warn_for, 0);
151 
152  if (! retval)
153  error ("%s: '%s' is not valid as a function",
154  warn_for.c_str (), fname.c_str ());
155 
156  warning ("%s: passing function body as a string is obsolete; please use anonymous functions",
157  warn_for.c_str ());
158  }
159 
160  return retval;
161 }
162 
165 {
166  int n = 1;
167 
168  size_t pos = 0;
169 
170  size_t len = text.length ();
171 
172  while ((pos = text.find ('.', pos)) != std::string::npos)
173  {
174  if (++pos == len)
175  break;
176 
177  n++;
178  }
179 
180  string_vector retval (n);
181 
182  pos = 0;
183 
184  for (int i = 0; i < n; i++)
185  {
186  len = text.find ('.', pos);
187 
188  if (len != std::string::npos)
189  len -= pos;
190 
191  retval[i] = text.substr (pos, len);
192 
193  if (len != std::string::npos)
194  pos += len + 1;
195  }
196 
197  return retval;
198 }
199 
200 static inline bool
202 {
203  bool retval = false;
204 
205  if (! name.empty ())
206  {
207  octave::symbol_scope scope = symtab.current_scope ();
208 
209  octave_value val = scope ? scope.varval (name) : octave_value ();
210 
211  retval = val.is_defined ();
212  }
213 
214  return retval;
215 }
216 
219  std::string& prefix, std::string& hint)
220 {
221  string_vector names;
222 
223  size_t pos = text.rfind ('.');
224  bool array = false;
225 
226  if (pos != std::string::npos)
227  {
228  if (pos == text.length ())
229  hint = "";
230  else
231  hint = text.substr (pos+1);
232 
233  prefix = text.substr (0, pos);
234 
235  if (prefix == "")
236  {
237  array = true;
238  prefix = find_indexed_expression (text);
239  }
240 
241  std::string base_name = prefix;
242 
243  pos = base_name.find_first_of ("{(. ");
244 
245  if (pos != std::string::npos)
246  base_name = base_name.substr (0, pos);
247 
248  octave::symbol_table& symtab
249  = octave::__get_symbol_table__ ("generate_struct_completions");
250 
251  if (is_variable (symtab, base_name))
252  {
253  int parse_status;
254 
256 
259 
260  discard_error_messages = true;
262 
263  try
264  {
265  octave_value tmp = octave::eval_string (prefix, true, parse_status);
266 
267  frame.run ();
268 
269  if (tmp.is_defined ()
270  && (tmp.isstruct () || tmp.isjava () || tmp.is_classdef_object ()))
271  names = tmp.map_keys ();
272  }
273  catch (const octave::execution_exception&)
274  {
276  }
277  }
278  }
279 
280  // Undo look-back that found the array expression,
281  // but insert an extra "." to distinguish from the non-struct case.
282  if (array)
283  prefix = ".";
284 
285  return names;
286 }
287 
288 // FIXME: this will have to be much smarter to work "correctly".
289 bool
290 looks_like_struct (const std::string& text, char prev_char)
291 {
292  bool retval = (! text.empty ()
293  && (text != "." || prev_char == ')' || prev_char == '}')
294  && text.find_first_of (octave::sys::file_ops::dir_sep_chars ()) == std::string::npos
295  && text.find ("..") == std::string::npos
296  && text.rfind ('.') != std::string::npos);
297 
298 #if 0
299  symbol_record *sr = curr_sym_tab->lookup (text);
300 
301  if (sr && ! sr->is_function ())
302  {
303  int parse_status;
304 
306 
308 
309  discard_error_messages = true;
310 
311  octave_value tmp = eval_string (text, true, parse_status);
312 
313  frame.run ();
314 
315  retval = (tmp.is_defined () && tmp.isstruct ());
316  }
317 #endif
318 
319  return retval;
320 }
321 
322 static octave_value
324 {
325  if (args.length () != 1)
326  print_usage ();
327 
328  if (! args(0).is_string ())
329  error ("isglobal: NAME must be a string");
330 
331  octave::symbol_scope scope = symtab.current_scope ();
332 
333  std::string name = args(0).string_value ();
334 
335  return scope && scope.is_global (name);
336 }
337 
338 DEFMETHOD (isglobal, interp, args, ,
339  doc: /* -*- texinfo -*-
340 @deftypefn {} {} isglobal (@var{name})
341 Return true if @var{name} is a globally visible variable.
342 
343 For example:
344 
345 @example
346 @group
347 global x
348 isglobal ("x")
349  @result{} 1
350 @end group
351 @end example
352 @seealso{isvarname, exist}
353 @end deftypefn */)
354 {
355  octave::symbol_table& symtab = interp.get_symbol_table ();
356 
357  return do_isglobal (symtab, args);
358 }
359 
360 /*
361 %!test
362 %! global x;
363 %! assert (isglobal ("x"), true);
364 
365 %!error isglobal ()
366 %!error isglobal ("a", "b")
367 %!error isglobal (1)
368 */
369 
370 static int
372  const std::string& type = "any")
373 {
374  if (octave::is_keyword (name))
375  return 0;
376 
377  bool search_any = type == "any";
378  bool search_var = type == "var";
379  bool search_dir = type == "dir";
380  bool search_file = type == "file";
381  bool search_builtin = type == "builtin";
382  bool search_class = type == "class";
383 
384  if (! (search_any || search_var || search_dir || search_file ||
385  search_builtin || search_class))
386  error (R"(exist: unrecognized type argument "%s")", type.c_str ());
387 
388  octave::symbol_table& symtab = interp.get_symbol_table ();
389 
390  if (search_any || search_var)
391  {
392  octave::symbol_scope scope = symtab.current_scope ();
393 
394  octave_value val = scope ? scope.varval (name) : octave_value ();
395 
396  if (val.is_constant () || val.isobject ()
397  || val.is_function_handle ()
398  || val.is_anonymous_function ()
399  || val.is_inline_function ())
400  return 1;
401 
402  if (search_var)
403  return 0;
404  }
405 
406  // We shouldn't need to look in the global symbol table, since any name
407  // that is visible in the current scope will be in the local symbol table.
408 
409  // Command line function which Matlab does not support
410  if (search_any)
411  {
412  octave_value val = symtab.find_cmdline_function (name);
413 
414  if (val.is_defined ())
415  return 103;
416  }
417 
418  if (search_any || search_file || search_dir)
419  {
421 
422  if (file_name.empty ())
423  {
424  octave::load_path& lp = interp.get_load_path ();
425 
426  file_name = lp.find_fcn (name);
427  }
428 
429  size_t len = file_name.length ();
430 
431  if (len > 0)
432  {
433  if (search_any || search_file)
434  {
435  if (len > 4 && (file_name.substr (len-4) == ".oct"
436  || file_name.substr (len-4) == ".mex"))
437  return 3;
438  else
439  return 2;
440  }
441  }
442 
443  file_name = file_in_path (name, "");
444 
445  if (file_name.empty ())
446  file_name = name;
447 
448  octave::sys::file_stat fs (file_name);
449 
450  if (fs)
451  {
452  if (search_any || search_file)
453  {
454  if (fs.is_dir ())
455  return 7;
456 
457  len = file_name.length ();
458 
459  if (len > 4 && (file_name.substr (len-4) == ".oct"
460  || file_name.substr (len-4) == ".mex"))
461  return 3;
462  else
463  return 2;
464  }
465  else if (search_dir && fs.is_dir ())
466  return 7;
467  }
468 
469  if (search_file || search_dir)
470  return 0;
471  }
472 
473  if (search_any || search_builtin)
474  {
475  if (symtab.is_built_in_function_name (name))
476  return 5;
477 
478  if (search_builtin)
479  return 0;
480  }
481 
482  return 0;
483 }
484 
485 int
487 {
488  octave::interpreter& interp = octave::__get_interpreter__ ("symbol_exist");
489 
490  return symbol_exist (interp, name, type);
491 }
492 
493 
494 #define GET_IDX(LEN) \
495  static_cast<int> ((LEN-1) * static_cast<double> (rand ()) / RAND_MAX)
496 
499 {
500  static const std::string alpha
501  = "abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ";
502 
503  static size_t len = alpha.length ();
504 
505  std::string nm = basename + alpha[GET_IDX (len)];
506 
507  size_t pos = nm.length ();
508 
509  if (nm.substr (0, 2) == "__")
510  nm.append ("__");
511 
512  octave::interpreter& interp
513  = octave::__get_interpreter__ ("unique_symbol_name");
514 
515  while (symbol_exist (interp, nm, "any"))
516  nm.insert (pos++, 1, alpha[GET_IDX (len)]);
517 
518  return nm;
519 }
520 
521 DEFMETHOD (exist, interp, args, ,
522  doc: /* -*- texinfo -*-
523 @deftypefn {} {@var{c} =} exist (@var{name})
524 @deftypefnx {} {@var{c} =} exist (@var{name}, @var{type})
525 Check for the existence of @var{name} as a variable, function, file, directory,
526 or class.
527 
528 The return code @var{c} is one of
529 
530 @table @asis
531 @item 1
532 @var{name} is a variable.
533 
534 @item 2
535 @var{name} is an absolute filename, an ordinary file in Octave's @code{path},
536 or (after appending @samp{.m}) a function file in Octave's @code{path}.
537 
538 @item 3
539 @var{name} is a @samp{.oct} or @samp{.mex} file in Octave's @code{path}.
540 
541 @item 5
542 @var{name} is a built-in function.
543 
544 @item 7
545 @var{name} is a directory.
546 
547 @item 8
548 @var{name} is a class. (Note: not currently implemented)
549 
550 @item 103
551 @var{name} is a function not associated with a file (entered on the command
552 line).
553 
554 @item 0
555 @var{name} does not exist.
556 @end table
557 
558 If the optional argument @var{type} is supplied, check only for symbols of the
559 specified type. Valid types are
560 
561 @table @asis
562 @item @qcode{"var"}
563 Check only for variables.
564 
565 @item @qcode{"builtin"}
566 Check only for built-in functions.
567 
568 @item @qcode{"dir"}
569 Check only for directories.
570 
571 @item @qcode{"file"}
572 Check only for files and directories.
573 
574 @item @qcode{"class"}
575 Check only for classes. (Note: This option is accepted, but not currently
576 implemented)
577 @end table
578 
579 If no type is given, and there are multiple possible matches for name,
580 @code{exist} will return a code according to the following priority list:
581 variable, built-in function, oct-file, directory, file, class.
582 
583 @code{exist} returns 2 if a regular file called @var{name} is present in
584 Octave's search path. For information about other types of files not on the
585 search path use some combination of the functions @code{file_in_path} and
586 @code{stat} instead.
587 
588 Programming Note: If @var{name} is implemented by a buggy .oct/.mex file,
589 calling @var{exist} may cause Octave to crash. To maintain high performance,
590 Octave trusts .oct/.mex files instead of @nospell{sandboxing} them.
591 
592 @seealso{file_in_loadpath, file_in_path, dir_in_loadpath, stat}
593 @end deftypefn */)
594 {
595  int nargin = args.length ();
596 
598  print_usage ();
599 
600  std::string name = args(0).xstring_value ("exist: NAME must be a string");
601 
602  if (nargin == 2)
603  {
604  std::string type = args(1).xstring_value ("exist: TYPE must be a string");
605 
606  if (type == "class")
607  warning (R"(exist: "class" type argument is not implemented)");
608 
609  return ovl (symbol_exist (interp, name, type));
610  }
611  else
612  return ovl (symbol_exist (interp, name));
613 }
614 
615 /*
616 %!shared dirtmp, __var1
617 %! dirtmp = P_tmpdir ();
618 %! __var1 = 1;
619 
620 %!assert (exist ("__%Highly_unlikely_name%__"), 0)
621 %!assert (exist ("__var1"), 1)
622 %!assert (exist ("__var1", "var"), 1)
623 %!assert (exist ("__var1", "builtin"), 0)
624 %!assert (exist ("__var1", "dir"), 0)
625 %!assert (exist ("__var1", "file"), 0)
626 
627 %!test
628 %! if (isunix ())
629 %! assert (exist ("/bin/sh"), 2);
630 %! assert (exist ("/bin/sh", "file"), 2);
631 %! assert (exist ("/bin/sh", "dir"), 0);
632 %! assert (exist ("/dev/null"), 2);
633 %! assert (exist ("/dev/null", "file"), 2);
634 %! assert (exist ("/dev/null", "dir"), 0);
635 %! endif
636 
637 %!assert (exist ("print_usage"), 2)
638 %!assert (exist ("print_usage.m"), 2)
639 %!assert (exist ("print_usage", "file"), 2)
640 %!assert (exist ("print_usage", "dir"), 0)
641 
642 ## Don't search path for rooted relative filenames
643 %!assert (exist ("plot.m", "file"), 2)
644 %!assert (exist ("./plot.m", "file"), 0)
645 %!assert (exist ("./%nonexistentfile%", "file"), 0)
646 %!assert (exist ("%nonexistentfile%", "file"), 0)
647 
648 ## Don't search path for absolute filenames
649 %!test
650 %! tname = tempname (pwd ());
651 %! unwind_protect
652 %! ## open/close file to create it, equivalent of touch
653 %! fid = fopen (tname, "w");
654 %! fclose (fid);
655 %! [~, fname] = fileparts (tname);
656 %! assert (exist (fullfile (pwd (), fname), "file"), 2);
657 %! unwind_protect_cleanup
658 %! unlink (tname);
659 %! end_unwind_protect
660 %! assert (exist (fullfile (pwd (), "%nonexistentfile%"), "file"), 0);
661 
662 %!testif HAVE_CHOLMOD
663 %! assert (exist ("chol"), 3);
664 %! assert (exist ("chol.oct"), 3);
665 %! assert (exist ("chol", "file"), 3);
666 %! assert (exist ("chol", "builtin"), 0);
667 
668 %!assert (exist ("sin"), 5)
669 %!assert (exist ("sin", "builtin"), 5)
670 %!assert (exist ("sin", "file"), 0)
671 
672 %!assert (exist (dirtmp), 7)
673 %!assert (exist (dirtmp, "dir"), 7)
674 %!assert (exist (dirtmp, "file"), 7)
675 
676 %!error exist ()
677 %!error exist (1,2,3)
678 %!warning <"class" type argument is not implemented> exist ("a", "class");
679 %!error <TYPE must be a string> exist ("a", 1)
680 %!error <NAME must be a string> exist (1)
681 %!error <unrecognized type argument "foobar"> exist ("a", "foobar")
682 
683 */
684 
685 // Variable values.
686 
687 static bool
688 wants_local_change (const octave_value_list& args, int& nargin)
689 {
690  bool retval = false;
691 
692  if (nargin == 2)
693  {
694  if (! args(1).is_string () || args(1).string_value () != "local")
695  error_with_cfn (R"(second argument must be "local")");
696 
697  nargin = 1;
698  retval = true;
699  }
700 
701  return retval;
702 }
703 
704 static octave::unwind_protect *
705 curr_fcn_unwind_protect_frame (void)
706 {
708  = octave::__get_call_stack__ ("curr_fcn_unwind_protect_frame");
709 
710  octave_user_code *curr_usr_code = cs.caller_user_code ();
711 
712  octave_user_function *curr_usr_fcn
713  = (curr_usr_code && curr_usr_code->is_user_function ()
714  ? dynamic_cast<octave_user_function *> (curr_usr_code) : nullptr);
715 
716  return curr_usr_fcn ? curr_usr_fcn->unwind_protect_frame () : nullptr;
717 }
718 
719 template <typename T>
720 static bool
721 try_local_protect (T& var)
722 {
723  octave::unwind_protect *frame = curr_fcn_unwind_protect_frame ();
724 
725  if (frame)
726  {
727  frame->protect_var (var);
728  return true;
729  }
730  else
731  return false;
732 }
733 
735 set_internal_variable (bool& var, const octave_value_list& args,
736  int nargout, const char *nm)
737 {
739 
740  int nargin = args.length ();
741 
742  if (nargout > 0 || nargin == 0)
743  retval = var;
744 
745  if (wants_local_change (args, nargin))
746  {
747  if (! try_local_protect (var))
748  warning (R"("local" has no effect outside a function)");
749  }
750 
751  if (nargin > 1)
752  print_usage ();
753 
754  if (nargin == 1)
755  {
756  bool bval = args(0).xbool_value ("%s: argument must be a logical value", nm);
757 
758  var = bval;
759  }
760 
761  return retval;
762 }
763 
765 set_internal_variable (char& var, const octave_value_list& args,
766  int nargout, const char *nm)
767 {
769 
770  int nargin = args.length ();
771 
772  if (nargout > 0 || nargin == 0)
773  retval = var;
774 
775  if (wants_local_change (args, nargin))
776  {
777  if (! try_local_protect (var))
778  warning (R"("local" has no effect outside a function)");
779  }
780 
781  if (nargin > 1)
782  print_usage ();
783 
784  if (nargin == 1)
785  {
786  std::string sval = args(0).xstring_value ("%s: argument must be a single character", nm);
787 
788  switch (sval.length ())
789  {
790  case 1:
791  var = sval[0];
792  break;
793 
794  case 0:
795  var = '\0';
796  break;
797 
798  default:
799  error ("%s: argument must be a single character", nm);
800  break;
801  }
802  }
803 
804  return retval;
805 }
806 
808 set_internal_variable (int& var, const octave_value_list& args,
809  int nargout, const char *nm,
810  int minval, int maxval)
811 {
813 
814  int nargin = args.length ();
815 
816  if (nargout > 0 || nargin == 0)
817  retval = var;
818 
819  if (wants_local_change (args, nargin))
820  {
821  if (! try_local_protect (var))
822  warning (R"("local" has no effect outside a function)");
823  }
824 
825  if (nargin > 1)
826  print_usage ();
827 
828  if (nargin == 1)
829  {
830  int ival = args(0).xint_value ("%s: argument must be an integer value", nm);
831 
832  if (ival < minval)
833  error ("%s: arg must be greater than %d", nm, minval);
834  if (ival > maxval)
835  error ("%s: arg must be less than or equal to %d", nm, maxval);
836 
837  var = ival;
838  }
839 
840  return retval;
841 }
842 
844 set_internal_variable (double& var, const octave_value_list& args,
845  int nargout, const char *nm,
846  double minval, double maxval)
847 {
849 
850  int nargin = args.length ();
851 
852  if (nargout > 0 || nargin == 0)
853  retval = var;
854 
855  if (wants_local_change (args, nargin))
856  {
857  if (! try_local_protect (var))
858  warning (R"("local" has no effect outside a function)");
859  }
860 
861  if (nargin > 1)
862  print_usage ();
863 
864  if (nargin == 1)
865  {
866  double dval = args(0).xscalar_value ("%s: argument must be a scalar value", nm);
867 
868  if (dval < minval)
869  error ("%s: argument must be greater than %g", minval);
870  if (dval > maxval)
871  error ("%s: argument must be less than or equal to %g", maxval);
872 
873  var = dval;
874  }
875 
876  return retval;
877 }
878 
881  int nargout, const char *nm, bool empty_ok)
882 {
884 
885  int nargin = args.length ();
886 
887  if (nargout > 0 || nargin == 0)
888  retval = var;
889 
890  if (wants_local_change (args, nargin))
891  {
892  if (! try_local_protect (var))
893  warning (R"("local" has no effect outside a function)");
894  }
895 
896  if (nargin > 1)
897  print_usage ();
898 
899  if (nargin == 1)
900  {
901  std::string sval = args(0).xstring_value ("%s: first argument must be a string", nm);
902 
903  if (! empty_ok && sval.empty ())
904  error ("%s: value must not be empty", nm);
905 
906  var = sval;
907  }
908 
909  return retval;
910 }
911 
913 set_internal_variable (int& var, const octave_value_list& args,
914  int nargout, const char *nm, const char **choices)
915 {
917  int nchoices = 0;
918  while (choices[nchoices] != nullptr)
919  nchoices++;
920 
921  int nargin = args.length ();
922 
923  assert (var < nchoices);
924 
925  if (nargout > 0 || nargin == 0)
926  retval = choices[var];
927 
928  if (wants_local_change (args, nargin))
929  {
930  if (! try_local_protect (var))
931  warning (R"("local" has no effect outside a function)");
932  }
933 
934  if (nargin > 1)
935  print_usage ();
936 
937  if (nargin == 1)
938  {
939  std::string sval = args(0).xstring_value ("%s: first argument must be a string", nm);
940 
941  int i = 0;
942  for (; i < nchoices; i++)
943  {
944  if (sval == choices[i])
945  {
946  var = i;
947  break;
948  }
949  }
950  if (i == nchoices)
951  error (R"(%s: value not allowed ("%s"))", nm, sval.c_str ());
952  }
953 
954  return retval;
955 }
956 
959  int nargout, const char *nm, const char **choices)
960 {
962  int nchoices = 0;
963  while (choices[nchoices] != nullptr)
964  nchoices++;
965 
966  int nargin = args.length ();
967 
968  if (nargout > 0 || nargin == 0)
969  retval = var;
970 
971  if (wants_local_change (args, nargin))
972  {
973  if (! try_local_protect (var))
974  warning (R"("local" has no effect outside a function)");
975  }
976 
977  if (nargin > 1)
978  print_usage ();
979 
980  if (nargin == 1)
981  {
982  std::string sval = args(0).xstring_value ("%s: first argument must be a string", nm);
983 
984  int i = 0;
985  for (; i < nchoices; i++)
986  {
987  if (sval == choices[i])
988  {
989  var = sval;
990  break;
991  }
992  }
993  if (i == nchoices)
994  error (R"(%s: value not allowed ("%s"))", nm, sval.c_str ());
995  }
996 
997  return retval;
998 }
999 
1000 struct
1001 whos_parameter
1002 {
1003  char command;
1004  char modifier;
1005  int parameter_length;
1006  int first_parameter_length;
1007  int balance;
1008  std::string text;
1009  std::string line;
1010 };
1011 
1012 static void
1013 print_descriptor (std::ostream& os, std::list<whos_parameter> params)
1014 {
1015  // This method prints a line of information on a given symbol
1016  std::list<whos_parameter>::iterator i = params.begin ();
1017  std::ostringstream param_buf;
1018 
1019  octave::preserve_stream_state stream_state (os);
1020 
1021  while (i != params.end ())
1022  {
1023  whos_parameter param = *i;
1024 
1025  if (param.command != '\0')
1026  {
1027  // Do the actual printing
1028  switch (param.modifier)
1029  {
1030  case 'l':
1031  os << std::setiosflags (std::ios::left)
1032  << std::setw (param.parameter_length);
1033  param_buf << std::setiosflags (std::ios::left)
1034  << std::setw (param.parameter_length);
1035  break;
1036 
1037  case 'r':
1038  os << std::setiosflags (std::ios::right)
1039  << std::setw (param.parameter_length);
1040  param_buf << std::setiosflags (std::ios::right)
1041  << std::setw (param.parameter_length);
1042  break;
1043 
1044  case 'c':
1045  if (param.command != 's')
1046  {
1047  os << std::setiosflags (std::ios::left)
1048  << std::setw (param.parameter_length);
1049  param_buf << std::setiosflags (std::ios::left)
1050  << std::setw (param.parameter_length);
1051  }
1052  break;
1053 
1054  default:
1055  os << std::setiosflags (std::ios::left)
1056  << std::setw (param.parameter_length);
1057  param_buf << std::setiosflags (std::ios::left)
1058  << std::setw (param.parameter_length);
1059  }
1060 
1061  if (param.command == 's' && param.modifier == 'c')
1062  {
1063  int a, b;
1064 
1065  if (param.modifier == 'c')
1066  {
1067  a = param.first_parameter_length - param.balance;
1068  a = (a < 0 ? 0 : a);
1069  b = param.parameter_length - a - param.text.length ();
1070  b = (b < 0 ? 0 : b);
1071  os << std::setiosflags (std::ios::left) << std::setw (a)
1072  << "" << std::resetiosflags (std::ios::left) << param.text
1073  << std::setiosflags (std::ios::left)
1074  << std::setw (b) << ""
1075  << std::resetiosflags (std::ios::left);
1076  param_buf << std::setiosflags (std::ios::left)
1077  << std::setw (a)
1078  << "" << std::resetiosflags (std::ios::left)
1079  << param.line
1080  << std::setiosflags (std::ios::left)
1081  << std::setw (b) << ""
1082  << std::resetiosflags (std::ios::left);
1083  }
1084  }
1085  else
1086  {
1087  os << param.text;
1088  param_buf << param.line;
1089  }
1090  os << std::resetiosflags (std::ios::left)
1091  << std::resetiosflags (std::ios::right);
1092  param_buf << std::resetiosflags (std::ios::left)
1093  << std::resetiosflags (std::ios::right);
1094  i++;
1095  }
1096  else
1097  {
1098  os << param.text;
1099  param_buf << param.line;
1100  i++;
1101  }
1102  }
1103 
1104  os << param_buf.str ();
1105 }
1106 
1107 // FIXME: This is a bit of a kluge. We'd like to just use val.dims()
1108 // and if val is an object, expect that dims will call size if it is
1109 // overloaded by a user-defined method. But there are currently some
1110 // unresolved const issues that prevent that solution from working.
1111 // This same kluge is done in symtab.cc (do_workspace_info), fix there too.
1112 
1115 {
1116  octave_value tmp = val;
1117 
1118  Matrix sz = tmp.size ();
1119 
1120  dim_vector dv = dim_vector::alloc (sz.numel ());
1121 
1122  for (octave_idx_type i = 0; i < dv.ndims (); i++)
1123  dv(i) = sz(i);
1124 
1125  return dv.str ();
1126 }
1127 
1128 class
1130 {
1131 private:
1133  {
1136  const std::string& expr_str = "",
1137  const octave_value& expr_val = octave_value ())
1138  : name (expr_str.empty () ? sr.name () : expr_str),
1139  varval (),
1140  is_automatic (sr.is_automatic ()),
1141  is_complex (varval.iscomplex ()),
1142  is_formal (sr.is_formal ()),
1143  is_global (sr.is_global ()),
1144  is_persistent (sr.is_persistent ())
1145  {
1146  varval = (expr_val.is_undefined ()
1147  ? sr.varval (context) : expr_val);
1148 
1149  is_complex = varval.iscomplex ();
1150  }
1151 
1152  void display_line (std::ostream& os,
1153  const std::list<whos_parameter>& params) const
1154  {
1155  std::string dims_str = get_dims_str (varval);
1156 
1157  std::list<whos_parameter>::const_iterator i = params.begin ();
1158 
1159  octave::preserve_stream_state stream_state (os);
1160 
1161  while (i != params.end ())
1162  {
1163  whos_parameter param = *i;
1164 
1165  if (param.command != '\0')
1166  {
1167  // Do the actual printing.
1168 
1169  switch (param.modifier)
1170  {
1171  case 'l':
1172  os << std::setiosflags (std::ios::left)
1173  << std::setw (param.parameter_length);
1174  break;
1175 
1176  case 'r':
1177  os << std::setiosflags (std::ios::right)
1178  << std::setw (param.parameter_length);
1179  break;
1180 
1181  case 'c':
1182  if (param.command == 's')
1183  {
1184  int front = param.first_parameter_length
1185  - dims_str.find ('x');
1186  int back = param.parameter_length
1187  - dims_str.length ()
1188  - front;
1189  front = (front > 0) ? front : 0;
1190  back = (back > 0) ? back : 0;
1191 
1192  os << std::setiosflags (std::ios::left)
1193  << std::setw (front)
1194  << ""
1195  << std::resetiosflags (std::ios::left)
1196  << dims_str
1197  << std::setiosflags (std::ios::left)
1198  << std::setw (back)
1199  << ""
1200  << std::resetiosflags (std::ios::left);
1201  }
1202  else
1203  {
1204  os << std::setiosflags (std::ios::left)
1205  << std::setw (param.parameter_length);
1206  }
1207  break;
1208 
1209  default:
1210  error ("whos_line_format: modifier '%c' unknown",
1211  param.modifier);
1212 
1213  os << std::setiosflags (std::ios::right)
1214  << std::setw (param.parameter_length);
1215  }
1216 
1217  switch (param.command)
1218  {
1219  case 'a':
1220  {
1221  char tmp[6];
1222 
1223  tmp[0] = (is_automatic ? 'a' : ' ');
1224  tmp[1] = (is_complex ? 'c' : ' ');
1225  tmp[2] = (is_formal ? 'f' : ' ');
1226  tmp[3] = (is_global ? 'g' : ' ');
1227  tmp[4] = (is_persistent ? 'p' : ' ');
1228  tmp[5] = 0;
1229 
1230  os << tmp;
1231  }
1232  break;
1233 
1234  case 'b':
1235  os << varval.byte_size ();
1236  break;
1237 
1238  case 'c':
1239  os << varval.class_name ();
1240  break;
1241 
1242  case 'e':
1243  os << varval.numel ();
1244  break;
1245 
1246  case 'n':
1247  os << name;
1248  break;
1249 
1250  case 's':
1251  if (param.modifier != 'c')
1252  os << dims_str;
1253  break;
1254 
1255  case 't':
1256  os << varval.type_name ();
1257  break;
1258 
1259  default:
1260  error ("whos_line_format: command '%c' unknown",
1261  param.command);
1262  }
1263 
1264  os << std::resetiosflags (std::ios::left)
1265  << std::resetiosflags (std::ios::right);
1266  i++;
1267  }
1268  else
1269  {
1270  os << param.text;
1271  i++;
1272  }
1273  }
1274  }
1275 
1283  };
1284 
1285 public:
1286  symbol_info_list (void) : lst () { }
1287 
1288  symbol_info_list (const symbol_info_list& sil) : lst (sil.lst) { }
1289 
1290  symbol_info_list& operator = (const symbol_info_list& sil)
1291  {
1292  if (this != &sil)
1293  lst = sil.lst;
1294 
1295  return *this;
1296  }
1297 
1298  ~symbol_info_list (void) = default;
1299 
1302  {
1303  lst.push_back (symbol_info (sr, context));
1304  }
1305 
1308  const std::string& expr_str,
1309  const octave_value& expr_val)
1310  {
1311  lst.push_back (symbol_info (sr, context, expr_str, expr_val));
1312  }
1313 
1314  size_t size (void) const { return lst.size (); }
1315 
1316  bool empty (void) const { return lst.empty (); }
1317 
1318  octave_map
1319  map_value (const std::string& caller_function_name, int nesting_level) const
1320  {
1321  size_t len = lst.size ();
1322 
1323  Cell name_info (len, 1);
1324  Cell size_info (len, 1);
1325  Cell bytes_info (len, 1);
1326  Cell class_info (len, 1);
1327  Cell global_info (len, 1);
1328  Cell sparse_info (len, 1);
1329  Cell complex_info (len, 1);
1330  Cell nesting_info (len, 1);
1331  Cell persistent_info (len, 1);
1332 
1333  std::list<symbol_info>::const_iterator p = lst.begin ();
1334 
1335  for (size_t j = 0; j < len; j++)
1336  {
1337  const symbol_info& si = *p++;
1338 
1339  octave_scalar_map ni;
1340 
1341  ni.assign ("function", caller_function_name);
1342  ni.assign ("level", nesting_level);
1343 
1344  name_info(j) = si.name;
1345  global_info(j) = si.is_global;
1346  persistent_info(j) = si.is_persistent;
1347 
1348  octave_value val = si.varval;
1349 
1350  size_info(j) = val.size ();
1351  bytes_info(j) = val.byte_size ();
1352  class_info(j) = val.class_name ();
1353  sparse_info(j) = val.issparse ();
1354  complex_info(j) = val.iscomplex ();
1355  nesting_info(j) = ni;
1356  }
1357 
1358  octave_map info;
1359 
1360  info.assign ("name", name_info);
1361  info.assign ("size", size_info);
1362  info.assign ("bytes", bytes_info);
1363  info.assign ("class", class_info);
1364  info.assign ("global", global_info);
1365  info.assign ("sparse", sparse_info);
1366  info.assign ("complex", complex_info);
1367  info.assign ("nesting", nesting_info);
1368  info.assign ("persistent", persistent_info);
1369 
1370  return info;
1371  }
1372 
1373  void display (std::ostream& os)
1374  {
1375  if (! lst.empty ())
1376  {
1377  size_t bytes = 0;
1378  size_t elements = 0;
1379 
1380  std::list<whos_parameter> params = parse_whos_line_format ();
1381 
1382  print_descriptor (os, params);
1383 
1384  octave_stdout << "\n";
1385 
1386  for (const auto& syminfo : lst)
1387  {
1388  syminfo.display_line (os, params);
1389 
1390  octave_value val = syminfo.varval;
1391 
1392  elements += val.numel ();
1393  bytes += val.byte_size ();
1394  }
1395 
1396  os << "\nTotal is " << elements
1397  << (elements == 1 ? " element" : " elements")
1398  << " using " << bytes << (bytes == 1 ? " byte" : " bytes")
1399  << "\n";
1400  }
1401  }
1402 
1403  // Parse the string whos_line_format, and return a parameter list,
1404  // containing all information needed to print the given
1405  // attributes of the symbols.
1406  std::list<whos_parameter> parse_whos_line_format (void)
1407  {
1408  int idx;
1409  size_t format_len = Vwhos_line_format.length ();
1410  char garbage;
1411  std::list<whos_parameter> params;
1412 
1413  size_t bytes1;
1414  int elements1;
1415 
1416  std::string param_string = "abcenst";
1417  Array<int> param_length (dim_vector (param_string.length (), 1));
1418  Array<std::string> param_names (dim_vector (param_string.length (), 1));
1419  size_t pos_a, pos_b, pos_c, pos_e, pos_n, pos_s, pos_t;
1420 
1421  pos_a = param_string.find ('a'); // Attributes
1422  pos_b = param_string.find ('b'); // Bytes
1423  pos_c = param_string.find ('c'); // Class
1424  pos_e = param_string.find ('e'); // Elements
1425  pos_n = param_string.find ('n'); // Name
1426  pos_s = param_string.find ('s'); // Size
1427  pos_t = param_string.find ('t'); // Type
1428 
1429  param_names(pos_a) = "Attr";
1430  param_names(pos_b) = "Bytes";
1431  param_names(pos_c) = "Class";
1432  param_names(pos_e) = "Elements";
1433  param_names(pos_n) = "Name";
1434  param_names(pos_s) = "Size";
1435  param_names(pos_t) = "Type";
1436 
1437  for (size_t i = 0; i < param_string.length (); i++)
1438  param_length(i) = param_names(i).length ();
1439 
1440  // The attribute column needs size 5.
1441  param_length(pos_a) = 5;
1442 
1443  // Calculating necessary spacing for name column,
1444  // bytes column, elements column and class column
1445 
1446  for (const auto& syminfo : lst)
1447  {
1448  std::stringstream ss1, ss2;
1449  std::string str;
1450 
1451  str = syminfo.name;
1452  param_length(pos_n) = ((str.length ()
1453  > static_cast<size_t> (param_length(pos_n)))
1454  ? str.length () : param_length(pos_n));
1455 
1456  octave_value val = syminfo.varval;
1457 
1458  str = val.type_name ();
1459  param_length(pos_t) = ((str.length ()
1460  > static_cast<size_t> (param_length(pos_t)))
1461  ? str.length () : param_length(pos_t));
1462 
1463  elements1 = val.numel ();
1464  ss1 << elements1;
1465  str = ss1.str ();
1466  param_length(pos_e) = ((str.length ()
1467  > static_cast<size_t> (param_length(pos_e)))
1468  ? str.length () : param_length(pos_e));
1469 
1470  bytes1 = val.byte_size ();
1471  ss2 << bytes1;
1472  str = ss2.str ();
1473  param_length(pos_b) = ((str.length ()
1474  > static_cast<size_t> (param_length(pos_b)))
1475  ? str.length () : param_length (pos_b));
1476  }
1477 
1478  idx = 0;
1479  while (static_cast<size_t> (idx) < format_len)
1480  {
1481  whos_parameter param;
1482  param.command = '\0';
1483 
1484  if (Vwhos_line_format[idx] == '%')
1485  {
1486  bool error_encountered = false;
1487  param.modifier = 'r';
1488  param.parameter_length = 0;
1489 
1490  int a = 0;
1491  int b = -1;
1492  int balance = 1;
1493  unsigned int items;
1494  size_t pos;
1495  std::string cmd;
1496 
1497  // Parse one command from whos_line_format
1498  cmd = Vwhos_line_format.substr (idx, Vwhos_line_format.length ());
1499  pos = cmd.find (';');
1500  if (pos == std::string::npos)
1501  error ("parameter without ; in whos_line_format");
1502 
1503  cmd = cmd.substr (0, pos+1);
1504 
1505  idx += cmd.length ();
1506 
1507  // FIXME: use iostream functions instead of sscanf!
1508 
1509  if (cmd.find_first_of ("crl") != 1)
1510  items = sscanf (cmd.c_str (), "%c%c:%d:%d:%d;",
1511  &garbage, &param.command, &a, &b, &balance);
1512  else
1513  items = sscanf (cmd.c_str (), "%c%c%c:%d:%d:%d;",
1514  &garbage, &param.modifier, &param.command,
1515  &a, &b, &balance) - 1;
1516 
1517  if (items < 2)
1518  error ("whos_line_format: parameter structure without command in whos_line_format");
1519 
1520  // Exception case of bare class command 'c' without modifier 'l/r'
1521  if (param.modifier == 'c'
1522  && param_string.find (param.command) == std::string::npos)
1523  {
1524  param.modifier = 'r';
1525  param.command = 'c';
1526  }
1527 
1528  // Insert data into parameter
1529  param.first_parameter_length = 0;
1530  pos = param_string.find (param.command);
1531  if (pos == std::string::npos)
1532  error ("whos_line_format: '%c' is not a command", param.command);
1533 
1534  param.parameter_length = param_length(pos);
1535  param.text = param_names(pos);
1536  param.line.assign (param_names(pos).length (), '=');
1537 
1538  param.parameter_length = (a > param.parameter_length
1539  ? a : param.parameter_length);
1540  if (param.command == 's' && param.modifier == 'c' && b > 0)
1541  param.first_parameter_length = b;
1542 
1543  if (param.command == 's')
1544  {
1545  // Have to calculate space needed for printing
1546  // matrix dimensions Space needed for Size column is
1547  // hard to determine in prior, because it depends on
1548  // dimensions to be shown. That is why it is
1549  // recalculated for each Size-command int first,
1550  // rest = 0, total;
1551  int rest = 0;
1552  int first = param.first_parameter_length;
1553  int total = param.parameter_length;
1554 
1555  for (const auto& syminfo : lst)
1556  {
1557  octave_value val = syminfo.varval;
1558  std::string dims_str = get_dims_str (val);
1559  int first1 = dims_str.find ('x');
1560  int total1 = dims_str.length ();
1561  int rest1 = total1 - first1;
1562  rest = (rest1 > rest ? rest1 : rest);
1563  first = (first1 > first ? first1 : first);
1564  total = (total1 > total ? total1 : total);
1565  }
1566 
1567  if (param.modifier == 'c')
1568  {
1569  if (first < balance)
1570  first += balance - first;
1571  if (rest + balance < param.parameter_length)
1572  rest += param.parameter_length - rest - balance;
1573 
1574  param.parameter_length = first + rest;
1575  param.first_parameter_length = first;
1576  param.balance = balance;
1577  }
1578  else
1579  {
1580  param.parameter_length = total;
1581  param.first_parameter_length = 0;
1582  }
1583  }
1584  else if (param.modifier == 'c')
1585  error ("whos_line_format: modifier 'c' not available for command '%c'",
1586  param.command);
1587 
1588  // What happens if whos_line_format contains negative numbers
1589  // at param_length positions?
1590  param.balance = (b < 0 ? 0 : param.balance);
1591  param.first_parameter_length = (b < 0
1592  ? 0
1593  : param.first_parameter_length);
1594  param.parameter_length = (a < 0
1595  ? 0
1596  : (param.parameter_length
1597  < param_length(pos_s)
1598  ? param_length(pos_s)
1599  : param.parameter_length));
1600 
1601  // Parameter will not be pushed into parameter list if ...
1602  if (! error_encountered)
1603  params.push_back (param);
1604  }
1605  else
1606  {
1607  // Text string, to be printed as it is ...
1608  std::string text;
1609  size_t pos;
1610  text = Vwhos_line_format.substr (idx, Vwhos_line_format.length ());
1611  pos = text.find ('%');
1612  if (pos != std::string::npos)
1613  text = text.substr (0, pos);
1614 
1615  // Push parameter into list ...
1616  idx += text.length ();
1617  param.text=text;
1618  param.line.assign (text.length (), ' ');
1619  params.push_back (param);
1620  }
1621  }
1622 
1623  return params;
1624  }
1625 
1626 private:
1627  std::list<symbol_info> lst;
1628 
1629 };
1630 
1631 static octave_value
1633  bool return_list, bool verbose = false, std::string msg = "")
1634 {
1636 
1637  octave::symbol_table& symtab = interp.get_symbol_table ();
1638  octave::call_stack& cs = interp.get_call_stack ();
1639 
1640  std::string my_name = argv[0];
1641 
1642  bool global_only = false;
1643  bool have_regexp = false;
1644 
1645  int i;
1646  for (i = 1; i < argc; i++)
1647  {
1648  if (argv[i] == "-file")
1649  {
1650  // FIXME: This is an inefficient manner to implement this as the
1651  // variables are loaded in to a temporary context and then treated.
1652  // It would be better to refecat symbol_info_list to not store the
1653  // symbol records and then use it in load-save.cc (do_load) to
1654  // implement this option there so that the variables are never
1655  // stored at all.
1656  if (i == argc - 1)
1657  error ("%s: -file argument must be followed by a filename",
1658  my_name.c_str ());
1659 
1660  std::string nm = argv[i + 1];
1661 
1663 
1664  // Set up temporary scope.
1665 
1666  octave::symbol_scope tmp_scope ("$dummy_scope$");
1667 
1668  symtab.set_scope (tmp_scope);
1669 
1670  cs.push (tmp_scope, 0);
1672 
1673  octave::feval ("load", octave_value (nm), 0);
1674 
1675  std::string newmsg = "Variables in the file " + nm + ":\n\n";
1676 
1677  retval = do_who (interp, i, argv, return_list, verbose, newmsg);
1678 
1679  return retval;
1680  }
1681  else if (argv[i] == "-regexp")
1682  have_regexp = true;
1683  else if (argv[i] == "global")
1684  global_only = true;
1685  else if (argv[i][0] == '-')
1686  warning ("%s: unrecognized option '%s'", my_name.c_str (),
1687  argv[i].c_str ());
1688  else
1689  break;
1690  }
1691 
1692  int npats = argc - i;
1693  string_vector pats;
1694  if (npats > 0)
1695  {
1696  pats.resize (npats);
1697  for (int j = 0; j < npats; j++)
1698  pats[j] = argv[i+j];
1699  }
1700  else
1701  {
1702  pats.resize (++npats);
1703  pats[0] = "*";
1704  }
1705 
1706  symbol_info_list symbol_stats;
1707  std::list<std::string> symbol_names;
1708 
1709  octave::symbol_scope scope = symtab.current_scope ();
1710 
1712 
1713  for (int j = 0; j < npats; j++)
1714  {
1715  std::string pat = pats[j];
1716 
1717  if (have_regexp)
1718  {
1719  std::list<octave::symbol_record> tmp
1720  = (global_only
1721  ? symtab.regexp_global_variables (pat)
1722  : symtab.regexp_variables (pat));
1723 
1724  for (const auto& symrec : tmp)
1725  {
1726  if (symrec.is_variable (context))
1727  {
1728  if (verbose)
1729  symbol_stats.append (symrec, context);
1730  else
1731  symbol_names.push_back (symrec.name ());
1732  }
1733  }
1734  }
1735  else
1736  {
1737  size_t pos = pat.find_first_of (".({");
1738 
1739  if (pos != std::string::npos && pos > 0)
1740  {
1741  if (verbose)
1742  {
1743  // NOTE: we can only display information for
1744  // expressions based on global values if the variable is
1745  // global in the current scope because we currently have
1746  // no way of looking up the base value in the global
1747  // scope and then evaluating the arguments in the
1748  // current scope.
1749 
1750  std::string base_name = pat.substr (0, pos);
1751 
1752  if (scope && scope.is_variable (base_name))
1753  {
1755  = symtab.find_symbol (base_name);
1756 
1757  if (! global_only || sr.is_global ())
1758  {
1759  int parse_status;
1760 
1761  octave_value expr_val
1762  = octave::eval_string (pat, true, parse_status);
1763 
1764  symbol_stats.append (sr, context, pat, expr_val);
1765  }
1766  }
1767  }
1768  }
1769  else
1770  {
1771  std::list<octave::symbol_record> tmp
1772  = (global_only
1773  ? symtab.glob_global_variables (pat)
1774  : symtab.glob_variables (pat));
1775 
1776  for (const auto& symrec : tmp)
1777  {
1778  if (symrec.is_variable (context))
1779  {
1780  if (verbose)
1781  symbol_stats.append (symrec, context);
1782  else
1783  symbol_names.push_back (symrec.name ());
1784  }
1785  }
1786  }
1787  }
1788  }
1789 
1790  if (return_list)
1791  {
1792  if (verbose)
1793  {
1794  std::string caller_function_name;
1795  octave_function *caller = cs.caller ();
1796  if (caller)
1797  caller_function_name = caller->name ();
1798 
1799  retval = symbol_stats.map_value (caller_function_name, 1);
1800  }
1801  else
1802  retval = Cell (string_vector (symbol_names));
1803  }
1804  else if (! (symbol_stats.empty () && symbol_names.empty ()))
1805  {
1806  if (msg.empty ())
1807  if (global_only)
1808  octave_stdout << "Global variables:\n\n";
1809  else
1810  octave_stdout << "Variables in the current scope:\n\n";
1811  else
1812  octave_stdout << msg;
1813 
1814  if (verbose)
1815  symbol_stats.display (octave_stdout);
1816  else
1817  {
1818  string_vector names (symbol_names);
1819 
1821  }
1822 
1823  octave_stdout << "\n";
1824  }
1825 
1826  return retval;
1827 }
1828 
1829 DEFMETHOD (who, interp, args, nargout,
1830  doc: /* -*- texinfo -*-
1831 @deftypefn {} {} who
1832 @deftypefnx {} {} who pattern @dots{}
1833 @deftypefnx {} {} who option pattern @dots{}
1834 @deftypefnx {} {C =} who ("pattern", @dots{})
1835 List currently defined variables matching the given patterns.
1836 
1837 Valid pattern syntax is the same as described for the @code{clear} command.
1838 If no patterns are supplied, all variables are listed.
1839 
1840 By default, only variables visible in the local scope are displayed.
1841 
1842 The following are valid options, but may not be combined.
1843 
1844 @table @code
1845 @item global
1846 List variables in the global scope rather than the current scope.
1847 
1848 @item -regexp
1849 The patterns are considered to be regular expressions when matching the
1850 variables to display. The same pattern syntax accepted by the @code{regexp}
1851 function is used.
1852 
1853 @item -file
1854 The next argument is treated as a filename. All variables found within the
1855 specified file are listed. No patterns are accepted when reading variables
1856 from a file.
1857 @end table
1858 
1859 If called as a function, return a cell array of defined variable names
1860 matching the given patterns.
1861 @seealso{whos, isglobal, isvarname, exist, regexp}
1862 @end deftypefn */)
1863 {
1864  int argc = args.length () + 1;
1865 
1866  string_vector argv = args.make_argv ("who");
1867 
1868  return do_who (interp, argc, argv, nargout == 1);
1869 }
1870 
1871 /*
1872 %!test
1873 %! avar = magic (4);
1874 %! ftmp = [tempname() ".mat"];
1875 %! unwind_protect
1876 %! save (ftmp, "avar");
1877 %! vars = whos ("-file", ftmp);
1878 %! assert (numel (vars), 1);
1879 %! assert (isstruct (vars));
1880 %! assert (vars.name, "avar");
1881 %! assert (vars.size, [4, 4]);
1882 %! assert (vars.class, "double");
1883 %! assert (vars.bytes, 128);
1884 %! unwind_protect_cleanup
1885 %! unlink (ftmp);
1886 %! end_unwind_protect
1887 */
1888 
1889 DEFMETHOD (whos, interp, args, nargout,
1890  doc: /* -*- texinfo -*-
1891 @deftypefn {} {} whos
1892 @deftypefnx {} {} whos pattern @dots{}
1893 @deftypefnx {} {} whos option pattern @dots{}
1894 @deftypefnx {} {S =} whos ("pattern", @dots{})
1895 Provide detailed information on currently defined variables matching the
1896 given patterns.
1897 
1898 Options and pattern syntax are the same as for the @code{who} command.
1899 
1900 Extended information about each variable is summarized in a table with the
1901 following default entries.
1902 
1903 @table @asis
1904 @item Attr
1905 Attributes of the listed variable. Possible attributes are:
1906 
1907 @table @asis
1908 @item blank
1909 Variable in local scope
1910 
1911 @item @code{a}
1912 Automatic variable. An automatic variable is one created by the
1913 interpreter, for example @code{argn}.
1914 
1915 @item @code{c}
1916 Variable of complex type.
1917 
1918 @item @code{f}
1919 Formal parameter (function argument).
1920 
1921 @item @code{g}
1922 Variable with global scope.
1923 
1924 @item @code{p}
1925 Persistent variable.
1926 @end table
1927 
1928 @item Name
1929 The name of the variable.
1930 
1931 @item Size
1932 The logical size of the variable. A scalar is 1x1, a vector is
1933 @nospell{1xN} or @nospell{Nx1}, a 2-D matrix is @nospell{MxN}.
1934 
1935 @item Bytes
1936 The amount of memory currently used to store the variable.
1937 
1938 @item Class
1939 The class of the variable. Examples include double, single, char, uint16,
1940 cell, and struct.
1941 @end table
1942 
1943 The table can be customized to display more or less information through
1944 the function @code{whos_line_format}.
1945 
1946 If @code{whos} is called as a function, return a struct array of defined
1947 variable names matching the given patterns. Fields in the structure
1948 describing each variable are: name, size, bytes, class, global, sparse,
1949 complex, nesting, persistent.
1950 @seealso{who, whos_line_format}
1951 @end deftypefn */)
1952 {
1953  int argc = args.length () + 1;
1954 
1955  string_vector argv = args.make_argv ("whos");
1956 
1957  return do_who (interp, argc, argv, nargout == 1, true);
1958 }
1959 
1960 DEFMETHOD (mlock, interp, args, ,
1961  doc: /* -*- texinfo -*-
1962 @deftypefn {} {} mlock ()
1963 Lock the current function into memory so that it can't be cleared.
1964 @seealso{munlock, mislocked, persistent}
1965 @end deftypefn */)
1966 {
1967  if (args.length () != 0)
1968  print_usage ();
1969 
1970  octave::call_stack& cs = interp.get_call_stack ();
1971 
1972  octave_function *fcn = cs.caller ();
1973 
1974  if (! fcn)
1975  error ("mlock: invalid use outside a function");
1976 
1977  fcn->lock ();
1978 
1979  return ovl ();
1980 }
1981 
1982 DEFMETHOD (munlock, interp, args, ,
1983  doc: /* -*- texinfo -*-
1984 @deftypefn {} {} munlock ()
1985 @deftypefnx {} {} munlock (@var{fcn})
1986 Unlock the named function @var{fcn}.
1987 
1988 If no function is named then unlock the current function.
1989 @seealso{mlock, mislocked, persistent}
1990 @end deftypefn */)
1991 {
1992  int nargin = args.length ();
1993 
1994  if (nargin > 1)
1995  print_usage ();
1996 
1997  if (nargin == 1)
1998  {
1999  std::string name = args(0).xstring_value ("munlock: FCN must be a string");
2000 
2001  interp.munlock (name);
2002  }
2003  else
2004  {
2005  octave::call_stack& cs = interp.get_call_stack ();
2006 
2007  octave_function *fcn = cs.caller ();
2008 
2009  if (! fcn)
2010  error ("munlock: invalid use outside a function");
2011 
2012  fcn->unlock ();
2013  }
2014 
2015  return ovl ();
2016 }
2017 
2018 DEFMETHOD (mislocked, interp, args, ,
2019  doc: /* -*- texinfo -*-
2020 @deftypefn {} {} mislocked ()
2021 @deftypefnx {} {} mislocked (@var{fcn})
2022 Return true if the named function @var{fcn} is locked.
2023 
2024 If no function is named then return true if the current function is locked.
2025 @seealso{mlock, munlock, persistent}
2026 @end deftypefn */)
2027 {
2028  int nargin = args.length ();
2029 
2030  if (nargin > 1)
2031  print_usage ();
2032 
2034 
2035  if (nargin == 1)
2036  {
2037  std::string name = args(0).xstring_value ("mislocked: FCN must be a string");
2038 
2039  retval = interp.mislocked (name);
2040  }
2041  else
2042  {
2043  octave::call_stack& cs = interp.get_call_stack ();
2044 
2045  octave_function *fcn = cs.caller ();
2046 
2047  if (! fcn)
2048  error ("mislocked: invalid use outside a function");
2049 
2050  retval = fcn->islocked ();
2051  }
2052 
2053  return retval;
2054 }
2055 
2056 // Deleting names from the symbol tables.
2057 
2058 static inline bool
2059 name_matches_any_pattern (const std::string& nm, const string_vector& argv,
2060  int argc, int idx, bool have_regexp = false)
2061 {
2062  bool retval = false;
2063 
2064  for (int k = idx; k < argc; k++)
2065  {
2066  std::string patstr = argv[k];
2067  if (! patstr.empty ())
2068  {
2069  if (have_regexp)
2070  {
2071  if (octave::regexp::is_match (patstr, nm))
2072  {
2073  retval = true;
2074  break;
2075  }
2076  }
2077  else
2078  {
2079  glob_match pattern (patstr);
2080 
2081  if (pattern.match (nm))
2082  {
2083  retval = true;
2084  break;
2085  }
2086  }
2087  }
2088  }
2089 
2090  return retval;
2091 }
2092 
2093 static inline void
2094 maybe_warn_exclusive (bool exclusive)
2095 {
2096  if (exclusive)
2097  warning ("clear: ignoring --exclusive option");
2098 }
2099 
2100 static void
2101 do_clear_functions (octave::symbol_table& symtab,
2102  const string_vector& argv, int argc, int idx,
2103  bool exclusive = false)
2104 {
2105  if (idx == argc)
2106  symtab.clear_functions ();
2107  else
2108  {
2109  if (exclusive)
2110  {
2111  string_vector fcns = symtab.user_function_names ();
2112 
2113  int fcount = fcns.numel ();
2114 
2115  for (int i = 0; i < fcount; i++)
2116  {
2117  std::string nm = fcns[i];
2118 
2119  if (! name_matches_any_pattern (nm, argv, argc, idx))
2120  symtab.clear_function (nm);
2121  }
2122  }
2123  else
2124  {
2125  while (idx < argc)
2126  symtab.clear_function_pattern (argv[idx++]);
2127  }
2128  }
2129 }
2130 
2131 static void
2132 do_clear_globals (octave::symbol_table& symtab,
2133  const string_vector& argv, int argc, int idx,
2134  bool exclusive = false)
2135 {
2136  octave::symbol_scope scope = symtab.current_scope ();
2137 
2138  if (! scope)
2139  return;
2140 
2141  if (idx == argc)
2142  {
2143  string_vector gvars = symtab.global_variable_names ();
2144 
2145  int gcount = gvars.numel ();
2146 
2147  for (int i = 0; i < gcount; i++)
2148  {
2149  std::string name = gvars[i];
2150 
2151  scope.clear_variable (name);
2152  symtab.clear_global (name);
2153  }
2154  }
2155  else
2156  {
2157  if (exclusive)
2158  {
2159  string_vector gvars = symtab.global_variable_names ();
2160 
2161  int gcount = gvars.numel ();
2162 
2163  for (int i = 0; i < gcount; i++)
2164  {
2165  std::string name = gvars[i];
2166 
2167  if (! name_matches_any_pattern (name, argv, argc, idx))
2168  {
2169  scope.clear_variable (name);
2170  symtab.clear_global (name);
2171  }
2172  }
2173  }
2174  else
2175  {
2176  while (idx < argc)
2177  {
2178  std::string pattern = argv[idx++];
2179 
2181  symtab.clear_global_pattern (pattern);
2182  }
2183  }
2184  }
2185 }
2186 
2187 static void
2188 do_clear_variables (octave::symbol_table& symtab,
2189  const string_vector& argv, int argc, int idx,
2190  bool exclusive = false, bool have_regexp = false)
2191 {
2192  octave::symbol_scope scope = symtab.current_scope ();
2193 
2194  if (! scope)
2195  return;
2196 
2197  if (idx == argc)
2198  scope.clear_variables ();
2199  else
2200  {
2201  if (exclusive)
2202  {
2203  string_vector lvars = scope.variable_names ();
2204 
2205  int lcount = lvars.numel ();
2206 
2207  for (int i = 0; i < lcount; i++)
2208  {
2209  std::string nm = lvars[i];
2211  if (! name_matches_any_pattern (nm, argv, argc, idx, have_regexp))
2212  scope.clear_variable (nm);
2213  }
2214  }
2215  else
2216  {
2217  if (have_regexp)
2218  while (idx < argc)
2219  scope.clear_variable_regexp (argv[idx++]);
2220  else
2221  while (idx < argc)
2222  scope.clear_variable_pattern (argv[idx++]);
2223  }
2224  }
2225 }
2226 
2227 static void
2228 do_clear_symbols (octave::symbol_table& symtab,
2229  const string_vector& argv, int argc, int idx,
2230  bool exclusive = false)
2231 {
2232  if (idx == argc)
2233  {
2234  octave::symbol_scope scope = symtab.current_scope ();
2235 
2236  if (scope)
2237  scope.clear_variables ();
2238  }
2239  else
2240  {
2241  if (exclusive)
2242  {
2243  // FIXME: is this really what we want, or do we
2244  // somehow want to only clear the functions that are not
2245  // shadowed by local variables? It seems that would be a
2246  // bit harder to do.
2247 
2248  do_clear_variables (symtab, argv, argc, idx, exclusive);
2249  do_clear_functions (symtab, argv, argc, idx, exclusive);
2250  }
2251  else
2252  {
2253  while (idx < argc)
2254  symtab.clear_symbol_pattern (argv[idx++]);
2255  }
2256  }
2257 }
2259 static void
2260 do_matlab_compatible_clear (octave::symbol_table& symtab,
2261  const string_vector& argv, int argc, int idx)
2262 {
2263  // This is supposed to be mostly Matlab compatible.
2264 
2265  octave::symbol_scope scope = symtab.current_scope ();
2266 
2267  if (! scope)
2268  return;
2269 
2270  for (; idx < argc; idx++)
2271  {
2272  if (argv[idx] == "all"
2273  && ! scope.is_local_variable ("all"))
2274  {
2275  symtab.clear_all ();
2276  }
2277  else if (argv[idx] == "functions"
2278  && ! scope.is_local_variable ("functions"))
2279  {
2280  do_clear_functions (symtab, argv, argc, ++idx);
2281  }
2282  else if (argv[idx] == "global"
2283  && ! scope.is_local_variable ("global"))
2284  {
2285  do_clear_globals (symtab, argv, argc, ++idx);
2286  }
2287  else if (argv[idx] == "variables"
2288  && ! scope.is_local_variable ("variables"))
2289  {
2290  scope.clear_variables ();
2291  }
2292  else if (argv[idx] == "classes"
2293  && ! scope.is_local_variable ("classes"))
2294  {
2295  scope.clear_objects ();
2297  symtab.clear_all ();
2298  }
2299  else
2300  {
2301  symtab.clear_symbol_pattern (argv[idx]);
2302  }
2303  }
2304 }
2305 
2306 #define CLEAR_OPTION_ERROR(cond) \
2307  do \
2308  { \
2309  if (cond) \
2310  print_usage (); \
2311  } \
2312  while (0)
2313 
2314 DEFMETHOD (clear, interp, args, ,
2315  doc: /* -*- texinfo -*-
2316 @deftypefn {} {} clear [options] pattern @dots{}
2317 Delete the names matching the given patterns from the symbol table.
2318 
2319 The pattern may contain the following special characters:
2320 
2321 @table @code
2322 @item ?
2323 Match any single character.
2324 
2325 @item *
2326 Match zero or more characters.
2327 
2328 @item [ @var{list} ]
2329 Match the list of characters specified by @var{list}. If the first
2330 character is @code{!} or @code{^}, match all characters except those
2331 specified by @var{list}. For example, the pattern @samp{[a-zA-Z]} will
2332 match all lowercase and uppercase alphabetic characters.
2333 @end table
2334 
2335 For example, the command
2336 
2337 @example
2338 clear foo b*r
2339 @end example
2340 
2341 @noindent
2342 clears the name @code{foo} and all names that begin with the letter
2343 @code{b} and end with the letter @code{r}.
2344 
2345 If @code{clear} is called without any arguments, all user-defined
2346 variables (local and global) are cleared from the symbol table.
2347 
2348 If @code{clear} is called with at least one argument, only the visible
2349 names matching the arguments are cleared. For example, suppose you have
2350 defined a function @code{foo}, and then hidden it by performing the
2351 assignment @code{foo = 2}. Executing the command @kbd{clear foo} once
2352 will clear the variable definition and restore the definition of
2353 @code{foo} as a function. Executing @kbd{clear foo} a second time will
2354 clear the function definition.
2355 
2356 The following options are available in both long and short form
2357 
2358 @table @code
2359 @item -all, -a
2360 Clear all local and global user-defined variables and all functions from the
2361 symbol table.
2362 
2363 @item -exclusive, -x
2364 Clear the variables that don't match the following pattern.
2365 
2366 @item -functions, -f
2367 Clear the function names and the built-in symbols names.
2368 
2369 @item -global, -g
2370 Clear global symbol names.
2371 
2372 @item -variables, -v
2373 Clear local variable names.
2374 
2375 @item -classes, -c
2376 Clears the class structure table and clears all objects.
2377 
2378 @item -regexp, -r
2379 The arguments are treated as regular expressions as any variables that
2380 match will be cleared.
2381 @end table
2382 
2383 With the exception of @code{exclusive}, all long options can be used
2384 without the dash as well.
2385 @seealso{who, whos, exist}
2386 @end deftypefn */)
2387 {
2388  octave::symbol_table& symtab = interp.get_symbol_table ();
2389 
2390  int argc = args.length () + 1;
2391 
2392  string_vector argv = args.make_argv ("clear");
2393 
2394  if (argc == 1)
2395  {
2396  do_clear_globals (symtab, argv, argc, true);
2397  do_clear_variables (symtab, argv, argc, true);
2398 
2400  }
2401  else
2402  {
2403  int idx = 0;
2404 
2405  bool clear_all = false;
2406  bool clear_functions = false;
2407  bool clear_globals = false;
2408  bool clear_variables = false;
2409  bool clear_objects = false;
2410  bool exclusive = false;
2411  bool have_regexp = false;
2412  bool have_dash_option = false;
2413 
2414  octave::symbol_scope scope = symtab.current_scope ();
2415 
2416  while (++idx < argc)
2417  {
2418  if (argv[idx] == "-all" || argv[idx] == "-a")
2419  {
2420  CLEAR_OPTION_ERROR (have_dash_option && ! exclusive);
2421 
2422  have_dash_option = true;
2423  clear_all = true;
2424  }
2425  else if (argv[idx] == "-exclusive" || argv[idx] == "-x")
2426  {
2427  have_dash_option = true;
2428  exclusive = true;
2429  }
2430  else if (argv[idx] == "-functions" || argv[idx] == "-f")
2431  {
2432  CLEAR_OPTION_ERROR (have_dash_option && ! exclusive);
2433 
2434  have_dash_option = true;
2435  clear_functions = true;
2436  }
2437  else if (argv[idx] == "-global" || argv[idx] == "-g")
2438  {
2439  CLEAR_OPTION_ERROR (have_dash_option && ! exclusive);
2440 
2441  have_dash_option = true;
2442  clear_globals = true;
2443  }
2444  else if (argv[idx] == "-variables" || argv[idx] == "-v")
2445  {
2446  CLEAR_OPTION_ERROR (have_dash_option && ! exclusive);
2447 
2448  have_dash_option = true;
2449  clear_variables = true;
2450  }
2451  else if (argv[idx] == "-classes" || argv[idx] == "-c")
2452  {
2453  CLEAR_OPTION_ERROR (have_dash_option && ! exclusive);
2454 
2455  have_dash_option = true;
2456  clear_objects = true;
2457  }
2458  else if (argv[idx] == "-regexp" || argv[idx] == "-r")
2459  {
2460  CLEAR_OPTION_ERROR (have_dash_option && ! exclusive);
2461 
2462  have_dash_option = true;
2463  have_regexp = true;
2464  }
2465  else
2466  break;
2467  }
2468 
2469  if (idx <= argc)
2470  {
2471  if (! have_dash_option)
2472  do_matlab_compatible_clear (symtab, argv, argc, idx);
2473  else
2474  {
2475  if (clear_all)
2476  {
2477  maybe_warn_exclusive (exclusive);
2478 
2479  if (++idx < argc)
2480  warning ("clear: ignoring extra arguments after -all");
2481 
2482  symtab.clear_all ();
2483  }
2484  else if (have_regexp)
2485  {
2486  do_clear_variables (symtab, argv, argc, idx, exclusive, true);
2487  }
2488  else if (clear_functions)
2489  {
2490  do_clear_functions (symtab, argv, argc, idx, exclusive);
2491  }
2492  else if (clear_globals)
2493  {
2494  do_clear_globals (symtab, argv, argc, idx, exclusive);
2495  }
2496  else if (clear_variables)
2497  {
2498  do_clear_variables (symtab, argv, argc, idx, exclusive);
2499  }
2500  else if (clear_objects)
2501  {
2502  if (scope)
2503  scope.clear_objects ();
2505  symtab.clear_all ();
2506  }
2507  else
2508  {
2509  do_clear_symbols (symtab, argv, argc, idx, exclusive);
2510  }
2511  }
2512 
2514  }
2515  }
2516 
2517  return ovl ();
2518 }
2519 
2520 DEFUN (whos_line_format, args, nargout,
2521  doc: /* -*- texinfo -*-
2522 @deftypefn {} {@var{val} =} whos_line_format ()
2523 @deftypefnx {} {@var{old_val} =} whos_line_format (@var{new_val})
2524 @deftypefnx {} {} whos_line_format (@var{new_val}, "local")
2525 Query or set the format string used by the command @code{whos}.
2526 
2527 A full format string is:
2528 @c Set example in small font to prevent overfull line
2529 
2530 @smallexample
2531 %[modifier]<command>[:width[:left-min[:balance]]];
2532 @end smallexample
2533 
2534 The following command sequences are available:
2535 
2536 @table @code
2537 @item %a
2538 Prints attributes of variables (g=global, p=persistent, f=formal parameter,
2539 a=automatic variable).
2540 
2541 @item %b
2542 Prints number of bytes occupied by variables.
2543 
2544 @item %c
2545 Prints class names of variables.
2546 
2547 @item %e
2548 Prints elements held by variables.
2549 
2550 @item %n
2551 Prints variable names.
2552 
2553 @item %s
2554 Prints dimensions of variables.
2555 
2556 @item %t
2557 Prints type names of variables.
2558 @end table
2559 
2560 Every command may also have an alignment modifier:
2561 
2562 @table @code
2563 @item l
2564 Left alignment.
2565 
2566 @item r
2567 Right alignment (default).
2568 
2569 @item c
2570 Column-aligned (only applicable to command %s).
2571 @end table
2572 
2573 The @code{width} parameter is a positive integer specifying the minimum
2574 number of columns used for printing. No maximum is needed as the field will
2575 auto-expand as required.
2576 
2577 The parameters @code{left-min} and @code{balance} are only available when
2578 the column-aligned modifier is used with the command @samp{%s}.
2579 @code{balance} specifies the column number within the field width which
2580 will be aligned between entries. Numbering starts from 0 which indicates
2581 the leftmost column. @code{left-min} specifies the minimum field width to
2582 the left of the specified balance column.
2583 
2584 The default format is:
2585 
2586 @qcode{" %a:4; %ln:6; %cs:16:6:1; %rb:12; %lc:-1;@xbackslashchar{}n"}
2587 
2588 When called from inside a function with the @qcode{"local"} option, the
2589 variable is changed locally for the function and any subroutines it calls.
2590 The original variable value is restored when exiting the function.
2591 @seealso{whos}
2592 @end deftypefn */)
2593 {
2594  return SET_INTERNAL_VARIABLE (whos_line_format);
2595 }
2596 
2597 static std::string Vmissing_function_hook = "__unimplemented__";
2598 
2599 DEFUN (missing_function_hook, args, nargout,
2600  doc: /* -*- texinfo -*-
2601 @deftypefn {} {@var{val} =} missing_function_hook ()
2602 @deftypefnx {} {@var{old_val} =} missing_function_hook (@var{new_val})
2603 @deftypefnx {} {} missing_function_hook (@var{new_val}, "local")
2604 Query or set the internal variable that specifies the function to call when
2605 an unknown identifier is requested.
2606 
2607 When called from inside a function with the @qcode{"local"} option, the
2608 variable is changed locally for the function and any subroutines it calls.
2609 The original variable value is restored when exiting the function.
2610 @seealso{missing_component_hook}
2611 @end deftypefn */)
2612 {
2613  return SET_INTERNAL_VARIABLE (missing_function_hook);
2614 }
2615 
2616 void
2618 {
2619  // Don't do this if we're handling errors.
2620  if (buffer_error_messages == 0 && ! Vmissing_function_hook.empty ())
2621  {
2622  octave::symbol_table& symtab
2623  = octave::__get_symbol_table__ ("maybe_missing_function_hook");
2624 
2625  octave_value val = symtab.find_function (Vmissing_function_hook);
2626 
2627  if (val.is_defined ())
2628  {
2629  // Ensure auto-restoration.
2631  frame.protect_var (Vmissing_function_hook);
2632 
2633  // Clear the variable prior to calling the function.
2634  const std::string func_name = Vmissing_function_hook;
2635  Vmissing_function_hook.clear ();
2636 
2637  // Call.
2638  octave::feval (func_name, octave_value (name));
2639  }
2640  }
2641 }
2642 
2643 DEFMETHOD (__varval__, interp, args, ,
2644  doc: /* -*- texinfo -*-
2645 @deftypefn {} {} __varval__ (@var{name})
2646 Return the value of the variable @var{name} directly from the symbol table.
2647 @end deftypefn */)
2648 {
2649  if (args.length () != 1)
2650  print_usage ();
2651 
2652  std::string name = args(0).xstring_value ("__varval__: first argument must be a variable name");
2653 
2654  octave::symbol_scope scope = interp.get_current_scope ();
2655 
2656  return scope ? scope.varval (args(0).string_value ()) : octave_value ();
2657 }
2658 
2660 
2661 DEFUN (missing_component_hook, args, nargout,
2662  doc: /* -*- texinfo -*-
2663 @deftypefn {} {@var{val} =} missing_component_hook ()
2664 @deftypefnx {} {@var{old_val} =} missing_component_hook (@var{new_val})
2665 @deftypefnx {} {} missing_component_hook (@var{new_val}, "local")
2666 Query or set the internal variable that specifies the function to call when
2667 a component of Octave is missing.
2668 
2669 This can be useful for packagers that may split the Octave installation into
2670 multiple sub-packages, for example, to provide a hint to users for how to
2671 install the missing components.
2672 
2673 When called from inside a function with the @qcode{"local"} option, the
2674 variable is changed locally for the function and any subroutines it calls.
2675 The original variable value is restored when exiting the function.
2676 
2677 The hook function is expected to be of the form
2678 
2679 @example
2680 @var{fcn} (@var{component})
2681 @end example
2682 
2683 Octave will call @var{fcn} with the name of the function that requires the
2684 component and a string describing the missing component. The hook function
2685 should return an error message to be displayed.
2686 @seealso{missing_function_hook}
2687 @end deftypefn */)
2688 {
2689  return SET_INTERNAL_VARIABLE (missing_component_hook);
2690 }
2691 
2692 // The following functions are deprecated.
2693 
2694 void
2695 mlock (void)
2696 {
2698 
2699  interp.mlock ();
2700 }
2701 
2702 void
2703 munlock (const std::string& nm)
2704 {
2706 
2707  return interp.munlock (nm);
2708 }
2709 
2710 bool
2711 mislocked (const std::string& nm)
2712 {
2714 
2715  return interp.mislocked (nm);
2716 }
2717 
2718 void
2719 bind_ans (const octave_value& val, bool print)
2720 {
2722 
2723  tw.bind_ans (val, print);
2724 }
2725 
2726 void
2727 clear_mex_functions (void)
2728 {
2729  octave::symbol_table& symtab =
2730  octave::__get_symbol_table__ ("clear_mex_functions");
2731 
2732  symtab.clear_mex_functions ();
2733 }
2734 
2735 void
2736 clear_function (const std::string& nm)
2737 {
2738  octave::symbol_table& symtab = octave::__get_symbol_table__ ("clear_function");
2739 
2740  symtab.clear_function (nm);
2741 }
2742 
2743 void
2744 clear_variable (const std::string& nm)
2745 {
2746  octave::symbol_scope scope
2747  = octave::__get_current_scope__ ("clear_variable");
2748 
2749  if (scope)
2750  scope.clear_variable (nm);
2751 }
2752 
2753 void
2754 clear_symbol (const std::string& nm)
2755 {
2756  octave::symbol_table& symtab = octave::__get_symbol_table__ ("clear_symbol");
2757 
2758  symtab.clear_symbol (nm);
2759 }
2760 
2763 {
2764  octave::symbol_scope scope
2765  = octave::__get_current_scope__ ("lookup_function_handle");
2766 
2767  octave_value val = scope ? scope.varval (nm) : octave_value ();
2768 
2769  return val.is_function_handle () ? val : octave_value ();
2770 }
2771 
2773 get_global_value (const std::string& nm, bool silent)
2774 {
2775  octave::symbol_table& symtab =
2776  octave::__get_symbol_table__ ("get_global_value");
2777 
2778  octave_value val = symtab.global_varval (nm);
2779 
2780  if (val.is_undefined () && ! silent)
2781  error ("get_global_value: undefined symbol '%s'", nm.c_str ());
2782 
2783  return val;
2784 }
2785 
2786 void
2788 {
2789  octave::symbol_table& symtab =
2790  octave::__get_symbol_table__ ("set_global_value");
2791 
2792  symtab.global_assign (nm, val);
2793 }
2794 
2796 get_top_level_value (const std::string& nm, bool silent)
2797 {
2798  octave::symbol_table& symtab =
2799  octave::__get_symbol_table__ ("get_top_level_value");
2800 
2801  octave_value val = symtab.top_level_varval (nm);
2802 
2803  if (val.is_undefined () && ! silent)
2804  error ("get_top_level_value: undefined symbol '%s'", nm.c_str ());
2805 
2806  return val;
2807 }
2808 
2809 void
2811 {
2812  octave::symbol_table& symtab =
2813  octave::__get_symbol_table__ ("set_top_level_value");
2814 
2815  symtab.top_level_assign (nm, val);
2816 }
OCTINTERP_API octave_value_list feval(const std::string &name, const octave_value_list &args=octave_value_list(), int nargout=0)
std::string str(char sep='x') const
Definition: dim-vector.cc:73
OCTINTERP_API void clear_function(const std::string &nm)
void append(const octave::symbol_record &sr, octave::symbol_record::context_id context)
Definition: variables.cc:1300
OCTINTERP_API void set_top_level_value(const std::string &nm, const octave_value &val)
octave_value find_function(const std::string &name, const octave_value_list &args=octave_value_list(), bool local_funcs=true)
Definition: symtab.cc:412
static int left
Definition: randmtzig.cc:184
symbol_record find_symbol(const std::string &name, symbol_scope &sid)
Definition: symtab.h:109
virtual bool is_user_function(void) const
Definition: ov-base.h:473
OCTINTERP_API void clear_symbol(const std::string &nm)
Definition: Cell.h:37
bool is_global(void) const
Definition: symrec.h:653
#define DEFMETHOD(name, interp_name, args_name, nargout_name, doc)
Macro to define a builtin method.
Definition: defun.h:135
interpreter & __get_interpreter__(const std::string &who)
std::string get_dims_str(const octave_value &val)
Definition: variables.cc:1114
void display_line(std::ostream &os, const std::list< whos_parameter > &params) const
Definition: variables.cc:1152
fname
Definition: load-save.cc:767
std::string string_value(bool force=false) const
Definition: ov.h:955
void lock(void)
Definition: ov-fcn.h:148
void assign(const std::string &k, const Cell &val)
Definition: oct-map.h:351
static void recover_from_exception(void)
OCTINTERP_API void print_usage(void)
Definition: defun.cc:54
std::string dir_sep_chars(void)
Definition: file-ops.cc:242
identity matrix If supplied two scalar respectively For allows like xample val
Definition: data.cc:4986
int argc
Definition: load-save.cc:646
OCTINTERP_API void clear_variable(const std::string &nm)
symbol_scope current_scope(void)
Definition: symtab.h:77
std::string xstring_value(const char *fmt,...) const
octave_value_list & append(const octave_value &val)
Definition: ovl.cc:83
bool islocked(void) const
Definition: ov-fcn.h:160
for large enough k
Definition: lu.cc:617
bool looks_like_struct(const std::string &text, char prev_char)
Definition: variables.cc:290
tem check only for symbols of the specified type Valid types are table asis item and there are multiple possible matches for name
Definition: variables.cc:593
#define DEFUN(name, args_name, nargout_name, doc)
Macro to define a builtin function.
Definition: defun.h:53
void error(const char *fmt,...)
Definition: error.cc:578
void clear_all(bool force=false)
Definition: symtab.h:368
std::list< symbol_record > regexp_variables(const string_vector &patterns)
Definition: symtab.h:542
static void print_descriptor(std::ostream &os, std::list< whos_parameter > params)
Definition: variables.cc:1013
#define SET_INTERNAL_VARIABLE(NM)
Definition: variables.h:109
std::ostream & list_in_columns(std::ostream &, int width=0, const std::string &prefix="") const
Definition: str-vec.cc:195
nd deftypefn *void maybe_missing_function_hook(const std::string &name)
Definition: variables.cc:2216
void clear_variable(const std::string &name)
Definition: symscope.h:767
octave_user_code * caller_user_code(size_t nskip=0) const
Definition: call-stack.cc:164
symbol_info_list(void)
Definition: variables.cc:1286
OCTINTERP_API std::string file_in_path(const std::string &, const std::string &)
static llvm::LLVMContext & context
Definition: jit-typeinfo.cc:79
OCTINTERP_API std::string lookup_autoload(const std::string &nm)
static std::string Vwhos_line_format
Definition: variables.cc:71
size_t size(void) const
Definition: variables.cc:1314
symbol_scope __get_current_scope__(const std::string &who)
to define functions rather than attempting to enter them directly on the command line The block of commands is executed as soon as you exit the editor To avoid executing any simply delete all the lines from the buffer before leaving the editor When invoked with no edit the previously executed command
Definition: oct-hist.cc:587
static std::string basename(const std::string &s, bool strip_path=false)
s
Definition: file-io.cc:2729
void clear_variable_regexp(const std::string &pat)
Definition: symscope.h:779
in this the arguments are accumulated from left to right
Definition: data.cc:390
void append(const octave::symbol_record &sr, octave::symbol_record::context_id context, const std::string &expr_str, const octave_value &expr_val)
Definition: variables.cc:1306
void clear_global_pattern(const std::string &pattern)
Definition: symtab.cc:307
var
Definition: givens.cc:88
bool is_dir(void) const
Definition: file-stat.cc:57
void resize(octave_idx_type n, const std::string &rfv="")
Definition: str-vec.h:97
void push(octave_function *fcn)
Definition: call-stack.cc:357
octave_value arg
Definition: pr-output.cc:3244
void bind_ans(const octave_value &val, bool print)
Definition: pt-eval.cc:2798
std::list< symbol_record > glob_variables(const string_vector &patterns)
Definition: symtab.h:523
octave_function * fcn
Definition: ov-class.cc:1754
string_vector argv
Definition: load-save.cc:648
bool empty(void) const
Definition: variables.cc:1316
std::string unique_symbol_name(const std::string &basename)
Definition: variables.cc:498
calling an anonymous function involves an overhead quite comparable to the overhead of an m file function Passing a handle to a built in function is because the interpreter is not involved in the internal loop For a
Definition: cellfun.cc:400
octave::call_stack & cs
Definition: ov-class.cc:1752
OCTINTERP_API octave_value get_top_level_value(const std::string &nm, bool silent=false)
symbol_info(const octave::symbol_record &sr, octave::symbol_record::context_id context, const std::string &expr_str="", const octave_value &expr_val=octave_value())
Definition: variables.cc:1134
bool verbose
Definition: load-save.cc:667
then the function must return scalars which will be concatenated into the return array(s). If code
Definition: cellfun.cc:400
symbol_table & __get_symbol_table__(const std::string &who)
int buffer_error_messages
Definition: error.cc:112
create a structure array and initialize its values The dimensions of each cell array of values must match Singleton cells and non cell values are repeated so that they fill the entire array If the cells are empty
Definition: ov-struct.cc:1736
std::list< std::string > user_function_names(void)
Definition: symtab.h:561
OCTAVE_EXPORT octave_value_list isdir nd deftypefn *std::string nm
Definition: utils.cc:975
std::list< symbol_info > lst
Definition: variables.cc:1627
OCTAVE_EXPORT octave_value_list return the number of command line arguments passed to Octave If called with the optional argument the function xample nargout(@histc)
Definition: ov-usr-fcn.cc:997
std::string find_fcn(const std::string &fcn, std::string &dir_name, const std::string &pack_name="")
Definition: load-path.h:109
nd example oindent opens the file binary numeric values will be read assuming they are stored in IEEE format with the least significant bit first
Definition: file-io.cc:587
OCTINTERP_API octave_value_list eval_string(const std::string &, bool silent, int &parse_status, int nargout)
load_path & get_load_path(void)
Definition: interpreter.h:164
octave_function * caller(void) const
Definition: call-stack.h:118
OCTINTERP_API bool mislocked(const std::string &)
void error_with_cfn(const char *fmt,...)
Definition: error.cc:608
void clear_objects(void)
Definition: symscope.h:761
symbol_record::context_id current_context(void) const
Definition: symscope.h:669
std::string str
Definition: hash.cc:118
bool mislocked(const std::string &nm)
string_vector get_struct_elts(const std::string &text)
Definition: variables.cc:164
void munlock(const std::string &nm)
void clear_variables(void)
Definition: symscope.h:755
string_vector generate_struct_completions(const std::string &text, std::string &prefix, std::string &hint)
Definition: variables.cc:218
string_vector make_argv(const std::string &="") const
Definition: ovl.cc:212
static bool is_variable(octave::symbol_table &symtab, const std::string &name)
Definition: variables.cc:201
double tmp
Definition: data.cc:6252
octave_value retval
Definition: data.cc:6246
std::list< std::string > global_variable_names(void)
Definition: symtab.h:577
OCTINTERP_API octave_value lookup_function_handle(const std::string &nm)
OCTINTERP_API void munlock(const std::string &)
OCTINTERP_API void bind_ans(const octave_value &val, bool print)
idx type
Definition: ov.cc:3114
Array< std::string > param
Definition: urlwrite.cc:124
Definition: dMatrix.h:36
sz
Definition: data.cc:5264
bool is_match(const std::string &buffer)
Definition: lo-regexp.cc:430
bool is_keyword(const std::string &s)
is longer than or if then or only for unique occurrences of the complete pattern(false). The default is true. If a cell array of strings ar
Definition: strfind.cc:190
std::list< whos_parameter > parse_whos_line_format(void)
Definition: variables.cc:1406
static dim_vector alloc(int n)
Definition: dim-vector.h:264
end deftypefn *return set_internal_variable(Vsvd_driver, args, nargout, "svd_driver", driver_names)
octave_value varval(const std::string &name) const
Definition: symscope.h:727
OCTINTERP_API void set_global_value(const std::string &nm, const octave_value &val)
symbol_table & get_symbol_table(void)
Definition: interpreter.h:169
static std::string Vmissing_component_hook
Definition: variables.cc:2258
void clear_mex_functions(void)
Definition: symtab.h:461
void unlock(void)
Definition: ov-fcn.h:154
octave_map map_value(const std::string &caller_function_name, int nesting_level) const
Definition: variables.cc:1319
void warning(const char *fmt,...)
Definition: error.cc:801
octave::unwind_protect frame
Definition: graphics.cc:12190
return octave_value(v1.char_array_value() . concat(v2.char_array_value(), ra_idx),((a1.is_sq_string()||a2.is_sq_string()) ? '\'' :'"'))
octave::unwind_protect * unwind_protect_frame(void)
Definition: ov-usr-fcn.h:88
OCTAVE_EXPORT octave_value_list the first data row corresponds to an index of zero The a spreadsheet style form such as the file is read until end of file is reached The such as text
Definition: dlmread.cc:194
#define octave_stdout
Definition: pager.h:174
static void clear_exemplar_map(void)
Definition: ov-class.cc:1107
octave_value global_varval(const std::string &name) const
Definition: symtab.h:174
octave_value top_level_varval(const std::string &name) const
Definition: symtab.h:186
OCTAVE_EXPORT octave_value_list isa nd deftypefn *return ovl(args(0).isinteger())
static int symbol_exist(octave::interpreter &interp, const std::string &name, const std::string &type="any")
Definition: variables.cc:371
bool is_variable(const std::string &name) const
Definition: symscope.h:732
OCTINTERP_API octave_value get_global_value(const std::string &nm, bool silent=false)
p
Definition: lu.cc:138
void assign(const std::string &k, const octave_value &val)
Definition: oct-map.h:227
call_stack & __get_call_stack__(const std::string &who)
symbol_info_list(const symbol_info_list &sil)
Definition: variables.cc:1288
void clear_functions(bool force=false)
Definition: symtab.h:384
void clear_symbol(const std::string &name)
Definition: symtab.h:397
octave_function * extract_function(const octave_value &arg, const std::string &warn_for, const std::string &fname, const std::string &header, const std::string &trailer)
Definition: variables.cc:125
octave_idx_type length(void) const
Definition: ovl.h:96
call_stack & get_call_stack(void)
b
Definition: cellfun.cc:400
Array< octave_idx_type > find(octave_idx_type n=-1, bool backward=false) const
Find indices of (at most n) nonzero elements.
Definition: Array.cc:2227
void clear_function_pattern(const std::string &pat)
Definition: symtab.h:407
octave::sys::file_stat fs(filename)
void add_method(T *obj, void(T::*method)(void))
std::string find_indexed_expression(const std::string &text)
Definition: input.cc:537
void assign(const idx_vector &i, const Array< T > &rhs, const T &rfv)
Indexed assignment (always with resize & fill).
Definition: Array.cc:1115
args.length() nargin
Definition: file-io.cc:589
for i
Definition: data.cc:5264
void display(std::ostream &os)
Definition: variables.cc:1373
void clear_function(const std::string &name)
Definition: symtab.h:392
void set_scope(const symbol_scope &sid)
Definition: symtab.h:92
bool is_string(void) const
Definition: ov.h:577
octave_idx_type ndims(void) const
Number of dimensions.
Definition: dim-vector.h:295
void clear_symbol_pattern(const std::string &pat)
Definition: symtab.h:422
void clear_global(const std::string &name)
Definition: symtab.cc:301
octave_value varval(context_id context) const
Definition: symrec.h:624
octave_idx_type numel(void) const
Number of elements in the array.
Definition: Array.h:366
bool is_local_variable(const std::string &name) const
Definition: symscope.h:837
octave_function * is_valid_function(const std::string &fcn_name, const std::string &warn_for, bool warn)
Definition: variables.cc:78
bool discard_warning_messages
Definition: error.cc:122
static octave_value do_who(octave::interpreter &interp, int argc, const string_vector &argv, bool return_list, bool verbose=false, std::string msg="")
Definition: variables.cc:1632
Vector representing the dimensions (size) of an Array.
Definition: dim-vector.h:87
bool discard_error_messages
Definition: error.cc:119
std::string name(void) const
Definition: ov-fcn.h:182
bool is_global(const std::string &name) const
Definition: symscope.h:842
If this string is the system will ring the terminal sometimes it is useful to be able to print the original representation of the string
Definition: utils.cc:888
void global_assign(const std::string &name, const octave_value &value=octave_value())
Definition: symtab.h:168
tree_evaluator & __get_evaluator__(const std::string &who)
#define GET_IDX(LEN)
Definition: variables.cc:494
void top_level_assign(const std::string &name, const octave_value &value=octave_value())
Definition: symtab.h:180
dim_vector dv
Definition: sub2ind.cc:263
std::list< symbol_record > regexp_global_variables(const std::string &pattern)
Definition: symtab.h:518
OCTINTERP_API void clear_mex_functions(void)
static octave_value do_isglobal(octave::symbol_table &symtab, const octave_value_list &args)
Definition: variables.cc:323
octave::stream os
Definition: file-io.cc:627
octave_idx_type length(void) const
Number of elements in the array.
Definition: Array.h:357
std::list< symbol_record > glob_global_variables(const std::string &pattern)
Definition: symtab.h:512
OCTINTERP_API void mlock(void)
std::list< std::string > variable_names(void)
Definition: symscope.h:832
void clear_variable_pattern(const std::string &pat)
Definition: symscope.h:773