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