GNU Octave  8.1.0
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-2023 The Octave Project Developers
4 //
5 // See the file COPYRIGHT.md in the top-level directory of this
6 // distribution or <https://octave.org/copyright/>.
7 //
8 // This file is part of Octave.
9 //
10 // Octave is free software: you can redistribute it and/or modify it
11 // under the terms of the GNU General Public License as published by
12 // the Free Software Foundation, either version 3 of the License, or
13 // (at your option) any later version.
14 //
15 // Octave is distributed in the hope that it will be useful, but
16 // WITHOUT ANY WARRANTY; without even the implied warranty of
17 // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
18 // GNU General Public License for more details.
19 //
20 // You should have received a copy of the GNU General Public License
21 // along with Octave; see the file COPYING. If not, see
22 // <https://www.gnu.org/licenses/>.
23 //
24 ////////////////////////////////////////////////////////////////////////
25 
26 #if defined (HAVE_CONFIG_H)
27 # include "config.h"
28 #endif
29 
30 #include <cstdio>
31 #include <cstring>
32 
33 #include <iomanip>
34 #include <list>
35 #include <set>
36 #include <string>
37 
38 #include "file-stat.h"
39 #include "oct-env.h"
40 #include "file-ops.h"
41 #include "glob-match.h"
42 #include "lo-regexp.h"
43 #include "str-vec.h"
44 
45 #include "Cell.h"
46 #include "defun.h"
47 #include "error.h"
48 #include "errwarn.h"
49 #include "event-manager.h"
50 #include "help.h"
51 #include "input.h"
52 #include "interpreter-private.h"
53 #include "interpreter.h"
54 #include "lex.h"
55 #include "load-path.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 "pt-eval.h"
65 #include "syminfo.h"
66 #include "symtab.h"
67 #include "sysdep.h"
68 #include "unwind-prot.h"
69 #include "utils.h"
70 #include "variables.h"
71 
72 // Attributes of variables and functions.
73 
74 // Is this octave_value a valid function?
75 
77 is_valid_function (const std::string& fcn_name,
78  const std::string& warn_for, bool warn)
79 {
80  octave_function *ans = nullptr;
81 
82  if (! fcn_name.empty ())
83  {
84  octave::symbol_table& symtab = octave::__get_symbol_table__ ();
85 
86  octave_value val = symtab.find_function (fcn_name);
87 
88  if (val.is_defined ())
89  ans = val.function_value (true);
90  }
91 
92  // FIXME: Should this be "err" and "error_for", rather than warn?
93  if (! ans && warn)
94  error ("%s: the symbol '%s' is not valid as a function",
95  warn_for.c_str (), fcn_name.c_str ());
96 
97  return ans;
98 }
99 
102  const std::string& warn_for, bool warn)
103 {
104  octave_function *ans = nullptr;
105 
106  std::string fcn_name;
107 
108  if (arg.is_string ())
109  {
110  fcn_name = arg.string_value ();
111 
112  ans = is_valid_function (fcn_name, warn_for, warn);
113  }
114  else if (warn)
115  // FIXME: Should this be "err" and "error_for", rather than warn?
116  error ("%s: argument must be a string containing function name",
117  warn_for.c_str ());
118 
119  return ans;
120 }
121 
123 
124 DEFMETHOD (isglobal, interp, args, ,
125  doc: /* -*- texinfo -*-
126 @deftypefn {} {@var{tf} =} isglobal (@var{name})
127 Return true if @var{name} is a globally visible variable.
128 
129 For example:
130 
131 @example
132 @group
133 global x
134 isglobal ("x")
135  @result{} 1
136 @end group
137 @end example
138 @seealso{isvarname, exist}
139 @end deftypefn */)
140 {
141  if (args.length () != 1)
142  print_usage ();
143 
144  std::string name = args(0).xstring_value ("isglobal: NAME must be a string");
145 
146  return ovl (interp.isglobal (name));
147 }
148 
149 /*
150 %!test
151 %! global x;
152 %! assert (isglobal ("x"), true);
153 %! clear -global x; # cleanup after test
154 
155 %!error isglobal ()
156 %!error isglobal ("a", "b")
157 %!error isglobal (1)
158 */
159 
160 static int
161 symbol_exist (interpreter& interp, const std::string& name,
162  const std::string& type = "any")
163 {
164  if (iskeyword (name))
165  return 0;
166 
167  bool search_any = type == "any";
168  bool search_var = type == "var";
169  bool search_dir = type == "dir";
170  bool search_file = type == "file";
171  bool search_builtin = type == "builtin";
172  bool search_class = type == "class";
173 
174  if (! (search_any || search_var || search_dir || search_file
175  || search_builtin || search_class))
176  error (R"(exist: unrecognized type argument "%s")", type.c_str ());
177 
178  if (search_any || search_var)
179  {
180  octave_value val = interp.varval (name);
181 
182  if (val.is_constant () || val.isobject ()
183  || val.is_function_handle ()
184  || val.is_anonymous_function ()
185  || val.is_inline_function ())
186  return 1;
187 
188  if (search_var)
189  return 0;
190  }
191 
192  symbol_table& symtab = interp.get_symbol_table ();
193 
194  // We shouldn't need to look in the global symbol table, since any name
195  // that is visible in the current scope will be in the local symbol table.
196 
197  if (search_any || search_file || search_dir || search_class)
198  {
199  bool have_fcn_ext = false;
200 
201  std::string xname = name;
202  std::string ext;
203 
204  std::size_t pos = name.rfind ('.');
205 
206  if (pos != std::string::npos)
207  {
208  ext = name.substr (pos+1);
209 
210  if (ext == "m" || ext == "oct" || ext == "mex")
211  {
212  xname = name.substr (0, pos);
213  have_fcn_ext = true;
214  }
215  }
216 
217  std::string file_name;
218 
219  if (search_any || search_file || search_class)
220  {
221  load_path& lp = interp.get_load_path ();
222 
223  // Look for class constructor first
224  file_name = lp.find_method (xname, xname);
225 
226  if (have_fcn_ext && ! file_name.empty ())
227  {
228  // Verify extension of file_name found matches ext of name.
229  pos = file_name.rfind ('.');
230 
231  if (pos != std::string::npos)
232  {
233  std::string fext = file_name.substr (pos+1);
234 
235  if (ext != fext)
236  file_name = "";
237  }
238  }
239 
240  if (search_any && file_name.empty ())
241  {
242  // Command line function which Matlab does not support
243  octave_value val = symtab.find_cmdline_function (xname);
244 
245  if (val.is_defined ())
246  return 103;
247  }
248 
249  // Autoloads can only have simple names without extensions.
250  if (! have_fcn_ext && file_name.empty ())
251  {
252  tree_evaluator& tw = interp.get_evaluator ();
253 
254  file_name = tw.lookup_autoload (name);
255  }
256 
257  // If nothing found, look for function using original name.
258  if (file_name.empty ())
259  file_name = lp.find_fcn (name);
260  }
261 
262  std::size_t len = file_name.length ();
263 
264  if (len > 0 && (search_any || search_file || search_class))
265  {
266  if (search_any || search_file)
267  {
268  if (len > 4 && (file_name.substr (len-4) == ".oct"
269  || file_name.substr (len-4) == ".mex"))
270  return 3;
271  }
272 
273  if (search_class)
274  {
275  octave_value oval = symtab.find_function (name);
276  if (oval.is_defined () && oval.is_classdef_meta ())
277  return 8;
278  else
279  return 0;
280  }
281 
282  return 2;
283  }
284 
285  // Nothing found in symbol table, try searching in path
286  file_name = file_in_path (name, "");
287 
288  if (file_name.empty ())
289  file_name = name;
290 
291  // "stat" doesn't work on UNC shares and drive letters.
292  if ((search_any || search_file) && drive_or_unc_share (file_name))
293  return 7;
294 
295  sys::file_stat fs (file_name);
296 
297  if (fs)
298  {
299  if (search_any || search_file)
300  {
301  if (fs.is_dir ())
302  return 7;
303 
304  len = file_name.length ();
305 
306  if (len > 4 && (file_name.substr (len-4) == ".oct"
307  || file_name.substr (len-4) == ".mex"))
308  return 3;
309  else
310  return 2;
311  }
312  else if (search_dir && fs.is_dir ())
313  return 7;
314  }
315 
316  if (search_file || search_dir)
317  return 0;
318  }
319 
320  if ((search_any || search_builtin)
321  && symtab.is_built_in_function_name (name))
322  return 5;
323 
324  return 0;
325 }
326 
327 int
328 symbol_exist (const std::string& name, const std::string& type)
329 {
330  octave::interpreter& interp = octave::__get_interpreter__ ();
331 
332  return octave::symbol_exist (interp, name, type);
333 }
334 
335 
336 #define GET_IDX(LEN) \
337  static_cast<int> (((LEN)-1) * static_cast<double> (rand ()) / RAND_MAX)
338 
339 std::string
340 unique_symbol_name (const std::string& basename)
341 {
342  static const std::string alpha
343  = "abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ";
344 
345  static std::size_t len = alpha.length ();
346 
347  std::string nm = basename + alpha[GET_IDX (len)];
348 
349  std::size_t pos = nm.length ();
350 
351  if (nm.substr (0, 2) == "__")
352  nm.append ("__");
353 
354  octave::interpreter& interp = octave::__get_interpreter__ ();
355 
356  while (symbol_exist (interp, nm, "any"))
357  nm.insert (pos++, 1, alpha[GET_IDX (len)]);
358 
359  return nm;
360 }
361 
362 DEFMETHOD (exist, interp, args, ,
363  doc: /* -*- texinfo -*-
364 @deftypefn {} {@var{c} =} exist (@var{name})
365 @deftypefnx {} {@var{c} =} exist (@var{name}, @var{type})
366 Check for the existence of @var{name} as a variable, function, file, directory,
367 or class.
368 
369 The return code @var{c} is one of
370 
371 @table @asis
372 @item 1
373 @var{name} is a variable.
374 
375 @item 2
376 @var{name} is an absolute filename, an ordinary file in Octave's @code{path},
377 or (after appending @samp{.m}) a function file in Octave's @code{path}.
378 
379 @item 3
380 @var{name} is a @samp{.oct} or @samp{.mex} file in Octave's @code{path}.
381 
382 @item 5
383 @var{name} is a built-in function.
384 
385 @item 7
386 @var{name} is a directory.
387 
388 @item 8
389 @var{name} is a classdef class.
390 
391 @item 103
392 @var{name} is a function not associated with a file (entered on the command
393 line).
394 
395 @item 0
396 @var{name} does not exist.
397 @end table
398 
399 If the optional argument @var{type} is supplied, check only for symbols of the
400 specified type. Valid types are
401 
402 @table @asis
403 @item @qcode{"var"}
404 Check only for variables.
405 
406 @item @qcode{"builtin"}
407 Check only for built-in functions.
408 
409 @item @qcode{"dir"}
410 Check only for directories.
411 
412 @item @qcode{"file"}
413 Check only for files and directories.
414 
415 @item @qcode{"class"}
416 Check only for classdef classes.
417 @end table
418 
419 If no type is given, and there are multiple possible matches for name,
420 @code{exist} will return a code according to the following priority list:
421 variable, built-in function, oct-file, directory, file, class.
422 
423 @code{exist} returns 2 if a regular file called @var{name} is present in
424 Octave's search path. For information about other types of files not on the
425 search path use some combination of the functions @code{file_in_path} and
426 @code{stat} instead.
427 
428 Programming Note: If @var{name} is implemented by a buggy .oct/.mex file,
429 calling @var{exist} may cause Octave to crash. To maintain high performance,
430 Octave trusts .oct/.mex files instead of @nospell{sandboxing} them.
431 
432 @seealso{file_in_loadpath, file_in_path, dir_in_loadpath, stat}
433 @end deftypefn */)
434 {
435  int nargin = args.length ();
436 
437  if (nargin < 1 || nargin > 2)
438  print_usage ();
439 
440  // For compatibility with undocumented Matlab behavior, return 0 if
441  // there is an empty built-in object as the only argument.
442  if (args(0).builtin_type () != btyp_unknown && args(0).isempty ())
443  return ovl (0);
444 
445  // Also for compatibility, return 0 if the second argument is an empty
446  // built-in object.
447  if (nargin == 2 && args(1).builtin_type () != btyp_unknown
448  && args(1).isempty ())
449  return ovl (0);
450 
451  std::string name = args(0).xstring_value ("exist: NAME must be a string");
452 
453  if (nargin == 2)
454  {
455  std::string type
456  = args(1).xstring_value ("exist: TYPE must be a string");
457 
458  return ovl (symbol_exist (interp, name, type));
459  }
460  else
461  return ovl (symbol_exist (interp, name));
462 }
463 
464 /*
465 %!shared dirtmp, __var1
466 %! dirtmp = P_tmpdir ();
467 %! __var1 = 1;
468 
469 %!assert (exist ("__%Highly_unlikely_name%__"), 0)
470 %!assert (exist ("__var1"), 1)
471 %!assert (exist ("__var1", "var"), 1)
472 %!assert (exist ("__var1", "builtin"), 0)
473 %!assert (exist ("__var1", "dir"), 0)
474 %!assert (exist ("__var1", "file"), 0)
475 %!assert (exist ("__var1", "class"), 0)
476 
477 %!testif ; isunix ()
478 %! assert (exist ("/bin/sh"), 2);
479 %! assert (exist ("/bin/sh", "file"), 2);
480 %! assert (exist ("/bin/sh", "dir"), 0);
481 %! assert (exist ("/dev/null"), 2);
482 %! assert (exist ("/dev/null", "file"), 2);
483 %! assert (exist ("/dev/null", "dir"), 0);
484 
485 %!assert (exist ("print_usage"), 2)
486 %!assert (exist ("print_usage.m"), 2)
487 %!assert (exist ("print_usage", "file"), 2)
488 %!assert (exist ("print_usage", "dir"), 0)
489 
490 ## Don't search path for rooted relative filenames
491 %!assert (exist ("plot.m", "file"), 2)
492 %!assert (exist ("./plot.m", "file"), 0)
493 %!assert (exist ("./%nonexistentfile%", "file"), 0)
494 %!assert (exist ("%nonexistentfile%", "file"), 0)
495 
496 ## Don't search path for absolute filenames
497 %!test
498 %! tname = tempname ();
499 %! unwind_protect
500 %! ## open/close file to create it, equivalent of touch
501 %! fid = fopen (tname, "w");
502 %! fclose (fid);
503 %! [~, fname] = fileparts (tname);
504 %! assert (exist (fullfile (tempdir (), fname), "file"), 2);
505 %! unwind_protect_cleanup
506 %! unlink (tname);
507 %! end_unwind_protect
508 %! assert (exist (fullfile (pwd (), "%nonexistentfile%"), "file"), 0);
509 
510 %!assert (exist ("fftw"), 3)
511 %!assert (exist ("fftw.oct"), 3)
512 %!assert (exist ("fftw", "file"), 3)
513 %!assert (exist ("fftw", "builtin"), 0)
514 
515 %!assert (exist ("ftp"), 2)
516 %!assert (exist ("ftp.m"), 2)
517 %!assert (exist ("@ftp/ftp"), 2)
518 %!assert (exist ("@ftp/ftp.m"), 2)
519 %!assert (exist ("ftp", "class"), 0)
520 
521 %!assert (exist ("inputParser"), 2)
522 %!assert (exist ("inputParser.m"), 2)
523 %!assert (exist ("inputParser", "class"), 8)
524 
525 %!assert (exist ("sin"), 5)
526 %!assert (exist ("sin", "builtin"), 5)
527 %!assert (exist ("sin", "file"), 0)
528 
529 %!assert (exist (dirtmp), 7)
530 %!assert (exist (dirtmp, "dir"), 7)
531 %!assert (exist (dirtmp, "file"), 7)
532 
533 %!error exist ()
534 %!error exist (1,2,3)
535 %!error <TYPE must be a string> exist ("a", 1)
536 %!error <NAME must be a string> exist (1)
537 %!error <unrecognized type argument "foobar"> exist ("a", "foobar")
538 
539 */
540 
541 // Variable values.
542 
543 static bool
544 wants_local_change (const octave_value_list& args, int& nargin)
545 {
546  bool retval = false;
547 
548  if (nargin == 2)
549  {
550  if (! args(1).is_string () || args(1).string_value () != "local")
551  error_with_cfn (R"(second argument must be "local")");
552 
553  nargin = 1;
554  retval = true;
555  }
556 
557  return retval;
558 }
559 
560 static octave::unwind_protect *
562 {
563  octave::tree_evaluator& tw = octave::__get_evaluator__ ();
564 
565  return tw.curr_fcn_unwind_protect_frame ();
566 }
567 
568 template <typename T>
569 static bool
571 {
572  octave::unwind_protect *frame = curr_fcn_unwind_protect_frame ();
573 
574  if (frame)
575  {
576  frame->protect_var (var);
577  return true;
578  }
579  else
580  return false;
581 }
582 
584 set_internal_variable (bool& var, const octave_value_list& args,
585  int nargout, const char *nm)
586 {
587  octave_value retval;
588 
589  int nargin = args.length ();
590 
591  if (nargout > 0 || nargin == 0)
592  retval = var;
593 
594  if (wants_local_change (args, nargin))
595  {
596  if (! try_local_protect (var))
597  warning (R"("local" has no effect outside a function)");
598  }
599 
600  if (nargin > 1)
601  print_usage ();
602 
603  if (nargin == 1)
604  {
605  bool bval = args(0).xbool_value ("%s: argument must be a logical value", nm);
606 
607  var = bval;
608  }
609 
610  return retval;
611 }
612 
614 set_internal_variable (char& var, const octave_value_list& args,
615  int nargout, const char *nm)
616 {
617  octave_value retval;
618 
619  int nargin = args.length ();
620 
621  if (nargout > 0 || nargin == 0)
622  retval = var;
623 
624  if (wants_local_change (args, nargin))
625  {
626  if (! try_local_protect (var))
627  warning (R"("local" has no effect outside a function)");
628  }
629 
630  if (nargin > 1)
631  print_usage ();
632 
633  if (nargin == 1)
634  {
635  std::string sval = args(0).xstring_value ("%s: argument must be a single character", nm);
636 
637  switch (sval.length ())
638  {
639  case 1:
640  var = sval[0];
641  break;
642 
643  case 0:
644  var = '\0';
645  break;
646 
647  default:
648  error ("%s: argument must be a single character", nm);
649  break;
650  }
651  }
652 
653  return retval;
654 }
655 
658  int nargout, const char *nm,
659  int minval, int maxval)
660 {
661  octave_value retval;
662 
663  int nargin = args.length ();
664 
665  if (nargout > 0 || nargin == 0)
666  retval = var;
667 
668  if (wants_local_change (args, nargin))
669  {
670  if (! try_local_protect (var))
671  warning (R"("local" has no effect outside a function)");
672  }
673 
674  if (nargin > 1)
675  print_usage ();
676 
677  if (nargin == 1)
678  {
679  int ival = args(0).xint_value ("%s: argument must be an integer value", nm);
680 
681  if (ival < minval)
682  error ("%s: arg must be greater than %d", nm, minval);
683  if (ival > maxval)
684  error ("%s: arg must be less than or equal to %d", nm, maxval);
685 
686  var = ival;
687  }
688 
689  return retval;
690 }
691 
693 set_internal_variable (double& var, const octave_value_list& args,
694  int nargout, const char *nm,
695  double minval, double maxval)
696 {
697  octave_value retval;
698 
699  int nargin = args.length ();
700 
701  if (nargout > 0 || nargin == 0)
702  retval = var;
703 
704  if (wants_local_change (args, nargin))
705  {
706  if (! try_local_protect (var))
707  warning (R"("local" has no effect outside a function)");
708  }
709 
710  if (nargin > 1)
711  print_usage ();
712 
713  if (nargin == 1)
714  {
715  double dval = args(0).xscalar_value ("%s: argument must be a scalar value", nm);
716 
717  if (dval < minval)
718  error ("%s: argument must be greater than %g", nm, minval);
719  if (dval > maxval)
720  error ("%s: argument must be less than or equal to %g", nm, maxval);
721 
722  var = dval;
723  }
724 
725  return retval;
726 }
727 
729 set_internal_variable (std::string& var, const octave_value_list& args,
730  int nargout, const char *nm, bool empty_ok)
731 {
732  octave_value retval;
733 
734  int nargin = args.length ();
735 
736  if (nargout > 0 || nargin == 0)
737  retval = var;
738 
739  if (wants_local_change (args, nargin))
740  {
741  if (! try_local_protect (var))
742  warning (R"("local" has no effect outside a function)");
743  }
744 
745  if (nargin > 1)
746  print_usage ();
747 
748  if (nargin == 1)
749  {
750  std::string sval = args(0).xstring_value ("%s: first argument must be a string", nm);
751 
752  if (! empty_ok && sval.empty ())
753  error ("%s: value must not be empty", nm);
754 
755  var = sval;
756  }
757 
758  return retval;
759 }
760 
763  int nargout, const char *nm, const char **choices)
764 {
765  octave_value retval;
766  int nchoices = 0;
767  while (choices[nchoices] != nullptr)
768  nchoices++;
769 
770  int nargin = args.length ();
771 
772  error_unless (var < nchoices);
773 
774  if (nargout > 0 || nargin == 0)
775  retval = choices[var];
776 
777  if (wants_local_change (args, nargin))
778  {
779  if (! try_local_protect (var))
780  warning (R"("local" has no effect outside a function)");
781  }
782 
783  if (nargin > 1)
784  print_usage ();
785 
786  if (nargin == 1)
787  {
788  std::string sval = args(0).xstring_value ("%s: first argument must be a string", nm);
789 
790  int i = 0;
791  for (; i < nchoices; i++)
792  {
793  if (sval == choices[i])
794  {
795  var = i;
796  break;
797  }
798  }
799  if (i == nchoices)
800  error (R"(%s: value not allowed ("%s"))", nm, sval.c_str ());
801  }
802 
803  return retval;
804 }
805 
807 set_internal_variable (std::string& var, const octave_value_list& args,
808  int nargout, const char *nm, const char **choices)
809 {
810  octave_value retval;
811  int nchoices = 0;
812  while (choices[nchoices] != nullptr)
813  nchoices++;
814 
815  int nargin = args.length ();
816 
817  if (nargout > 0 || nargin == 0)
818  retval = var;
819 
820  if (wants_local_change (args, nargin))
821  {
822  if (! try_local_protect (var))
823  warning (R"("local" has no effect outside a function)");
824  }
825 
826  if (nargin > 1)
827  print_usage ();
828 
829  if (nargin == 1)
830  {
831  std::string sval = args(0).xstring_value ("%s: first argument must be a string", nm);
832 
833  int i = 0;
834  for (; i < nchoices; i++)
835  {
836  if (sval == choices[i])
837  {
838  var = sval;
839  break;
840  }
841  }
842  if (i == nchoices)
843  error (R"(%s: value not allowed ("%s"))", nm, sval.c_str ());
844  }
845 
846  return retval;
847 }
848 
849 // NOTE: Calling Fmlock directly (without an associated stack frame)
850 // will probably not do what you expect because it will lock the calling
851 // function. You should use interpreter::mlock directly if you want to
852 // lock a .oct function. For .mex, you would normally use mexLock.
853 //
854 // FIXME: with the current implementation, calling "builtin ('mlock')"
855 // will also not do what you expect. Is there any reasonable way to fix
856 // that?
857 
858 DEFMETHOD (mlock, interp, args, ,
859  doc: /* -*- texinfo -*-
860 @deftypefn {} {} mlock ()
861 Lock the current function into memory so that it can't be removed with
862 @code{clear}.
863 @seealso{munlock, mislocked, persistent, clear}
864 @end deftypefn */)
865 {
866  if (args.length () != 0)
867  print_usage ();
868 
869  interp.mlock (true);
870 
871  return ovl ();
872 }
873 
874 DEFMETHOD (munlock, interp, args, ,
875  doc: /* -*- texinfo -*-
876 @deftypefn {} {} munlock ()
877 @deftypefnx {} {} munlock (@var{fcn})
878 Unlock the named function @var{fcn} so that it may be removed from memory with
879 @code{clear}.
880 
881 If no function is named then unlock the current function.
882 @seealso{mlock, mislocked, persistent, clear}
883 @end deftypefn */)
884 {
885  int nargin = args.length ();
886 
887  if (nargin > 1)
888  print_usage ();
889 
890  if (nargin == 1)
891  {
892  std::string name
893  = args(0).xstring_value ("munlock: FCN must be a string");
894 
895  interp.munlock (name);
896  }
897  else
898  interp.munlock (true);
899 
900  return ovl ();
901 }
902 
903 DEFMETHOD (mislocked, interp, args, ,
904  doc: /* -*- texinfo -*-
905 @deftypefn {} {@var{tf} =} mislocked ()
906 @deftypefnx {} {@var{tf} =} mislocked (@var{fcn})
907 Return true if the named function @var{fcn} is locked in memory.
908 
909 If no function is named then return true if the current function is locked.
910 @seealso{mlock, munlock, persistent, clear}
911 @end deftypefn */)
912 {
913  int nargin = args.length ();
914 
915  if (nargin > 1)
916  print_usage ();
917 
918  if (nargin == 1)
919  {
920  std::string name
921  = args(0).xstring_value ("mislocked: FCN must be a string");
922 
923  return ovl (interp.mislocked (name));
924  }
925  else
926  return ovl (interp.mislocked (true));
927 }
928 
929 // Deleting names from the symbol tables.
930 
931 static inline bool
932 name_matches_any_pattern (const std::string& nm, const string_vector& argv,
933  int argc, int idx, bool have_regexp = false)
934 {
935  bool retval = false;
936 
937  for (int k = idx; k < argc; k++)
938  {
939  std::string patstr = argv[k];
940  if (! patstr.empty ())
941  {
942  if (have_regexp)
943  {
944  if (regexp::is_match (patstr, nm))
945  {
946  retval = true;
947  break;
948  }
949  }
950  else
951  {
952  glob_match pattern (patstr);
953 
954  if (pattern.match (nm))
955  {
956  retval = true;
957  break;
958  }
959  }
960  }
961  }
962 
963  return retval;
964 }
965 
966 static inline void
967 maybe_warn_exclusive (bool exclusive)
968 {
969  if (exclusive)
970  warning ("clear: ignoring --exclusive option");
971 }
972 
973 static void
975  const string_vector& argv, int argc, int idx,
976  bool exclusive = false)
977 {
978  if (idx == argc)
979  interp.clear_functions ();
980  else
981  {
982  if (exclusive)
983  {
984  std::list<std::string> fcns = interp.user_function_names ();
985 
986  for (const auto& name : fcns)
987  {
988  if (! name_matches_any_pattern (name, argv, argc, idx))
989  interp.clear_function (name);
990  }
991  }
992  else
993  {
994  while (idx < argc)
995  interp.clear_function_pattern (argv[idx++]);
996  }
997  }
998 }
999 
1000 static void
1002  const string_vector& argv, int argc, int idx,
1003  bool exclusive = false)
1004 {
1005  if (idx == argc)
1006  {
1007  std::list<std::string> gvars = interp.global_variable_names ();
1008 
1009  for (const auto& name : gvars)
1010  {
1011  interp.clear_variable (name);
1012  interp.clear_global_variable (name);
1013  }
1014  }
1015  else
1016  {
1017  if (exclusive)
1018  {
1019  std::list<std::string> gvars = interp.global_variable_names ();
1020 
1021  for (const auto& name : gvars)
1022  {
1023  if (! name_matches_any_pattern (name, argv, argc, idx))
1024  {
1025  interp.clear_variable (name);
1026  interp.clear_global_variable (name);
1027  }
1028  }
1029  }
1030  else
1031  {
1032  while (idx < argc)
1033  {
1034  std::string pattern = argv[idx++];
1035 
1036  interp.clear_variable_pattern (pattern);
1037  interp.clear_global_variable_pattern (pattern);
1038  }
1039  }
1040  }
1041 }
1042 
1043 static void
1045  const string_vector& argv, int argc, int idx,
1046  bool exclusive = false, bool have_regexp = false)
1047 {
1048  if (idx == argc)
1049  interp.clear_variables ();
1050  else
1051  {
1052  if (exclusive)
1053  {
1054  std::list<std::string> lvars = interp.variable_names ();
1055 
1056  for (const auto& name : lvars)
1057  {
1058  if (! name_matches_any_pattern (name, argv, argc, idx,
1059  have_regexp))
1060  interp.clear_variable (name);
1061  }
1062  }
1063  else
1064  {
1065  if (have_regexp)
1066  while (idx < argc)
1067  interp.clear_variable_regexp (argv[idx++]);
1068  else
1069  while (idx < argc)
1070  interp.clear_variable_pattern (argv[idx++]);
1071  }
1072  }
1073 }
1074 
1075 static void
1077  const string_vector& argv, int argc, int idx,
1078  bool exclusive = false)
1079 {
1080  if (idx == argc)
1081  {
1082  interp.clear_variables ();
1083  }
1084  else
1085  {
1086  if (exclusive)
1087  {
1088  // FIXME: is this really what we want, or do we
1089  // somehow want to only clear the functions that are not
1090  // shadowed by local variables? It seems that would be a
1091  // bit harder to do.
1092 
1093  do_clear_variables (interp, argv, argc, idx, exclusive);
1094  do_clear_functions (interp, argv, argc, idx, exclusive);
1095  }
1096  else
1097  {
1098  while (idx < argc)
1099  interp.clear_symbol_pattern (argv[idx++]);
1100  }
1101  }
1102 }
1103 
1104 static void
1106  const string_vector& argv, int argc, int idx)
1107 {
1108  // This is supposed to be mostly Matlab compatible.
1109 
1110  for (; idx < argc; idx++)
1111  {
1112  if (argv[idx] == "all" && ! interp.is_local_variable ("all"))
1113  {
1114  interp.clear_all ();
1115  }
1116  else if (argv[idx] == "functions"
1117  && ! interp.is_local_variable ("functions"))
1118  {
1119  do_clear_functions (interp, argv, argc, ++idx);
1120  }
1121  else if (argv[idx] == "global"
1122  && ! interp.is_local_variable ("global"))
1123  {
1124  do_clear_globals (interp, argv, argc, ++idx);
1125  }
1126  else if (argv[idx] == "variables"
1127  && ! interp.is_local_variable ("variables"))
1128  {
1129  interp.clear_variables ();
1130  }
1131  else if (argv[idx] == "classes"
1132  && ! interp.is_local_variable ("classes"))
1133  {
1134  interp.clear_objects ();
1136  interp.clear_all ();
1137  }
1138  else
1139  {
1140  interp.clear_symbol_pattern (argv[idx]);
1141  }
1142  }
1143 }
1144 
1145 DEFMETHOD (clear, interp, args, ,
1146  doc: /* -*- texinfo -*-
1147 @deftypefn {} {} clear
1148 @deftypefnx {} {} clear @var{pattern} @dots{}
1149 @deftypefnx {} {} clear @var{options} @var{pattern} @dots{}
1150 Delete the names matching the given @var{pattern}s thereby freeing memory.
1151 
1152 The @var{pattern} may contain the following special characters:
1153 
1154 @table @code
1155 @item ?
1156 Match any single character.
1157 
1158 @item *
1159 Match zero or more characters.
1160 
1161 @item [ @var{list} ]
1162 Match the list of characters specified by @var{list}. If the first character
1163 is @code{!} or @code{^}, match all characters except those specified by
1164 @var{list}. For example, the pattern @code{[a-zA-Z]} will match all lowercase
1165 and uppercase alphabetic characters.
1166 @end table
1167 
1168 For example, the command
1169 
1170 @example
1171 clear foo b*r
1172 @end example
1173 
1174 @noindent
1175 clears the name @code{foo} and all names that begin with the letter @samp{b}
1176 and end with the letter @samp{r}.
1177 
1178 If @code{clear} is called without any arguments, all user-defined variables
1179 are cleared from the current workspace (i.e., local variables). Any global
1180 variables present will no longer be visible in the current workspace, but they
1181 will continue to exist in the global workspace. Functions are unaffected by
1182 this form of @code{clear}.
1183 
1184 The following options are available in both long and short form
1185 
1186 @table @code
1187 @item all, -all, -a
1188 Clear all local and global user-defined variables, and all functions from the
1189 symbol table.
1190 
1191 @item -exclusive, -x
1192 Clear variables that do @strong{not} match the following pattern.
1193 
1194 @item functions, -functions, -f
1195 Clear function names from the function symbol table. Persistent variables
1196 will be re-initialized to their default value unless the function has been
1197 locked in memory with @code{mlock}.
1198 
1199 @item global, -global, -g
1200 Clear global variable names.
1201 
1202 @item variables, -variables, -v
1203 Clear local variable names.
1204 
1205 @item classes, -classes, -c
1206 Clear the class structure table and all objects.
1207 
1208 @item -regexp, -r
1209 The @var{pattern} arguments are treated as regular expressions and any matches
1210 will be cleared.
1211 @end table
1212 
1213 With the exception of @option{-exclusive} and @option{-regexp}, all long
1214 options can be used without the dash as well. Note that, aside from
1215 @option{-exclusive}, only one other option may appear. All options must
1216 appear before any patterns.
1217 
1218 Programming Notes: The command @code{clear @var{name}} only clears the variable
1219 @var{name} when both a variable and a (shadowed) function named @var{name}
1220 are currently defined. For example, suppose you have defined a function
1221 @code{foo}, and then hidden it by performing the assignment @code{foo = 2}.
1222 Executing the command @code{clear foo} once will clear the variable
1223 definition and restore the definition of @code{foo} as a function.
1224 Executing @code{clear foo} a second time will clear the function definition.
1225 
1226 When a local variable name, which is linked to a global variable, is cleared
1227 only the local copy of the variable is removed. The global copy is untouched
1228 and can be restored with @code{global @var{global_varname}}. Conversely,
1229 @code{clear -g @var{global_varname}} will remove both the local and global
1230 variables.
1231 
1232 @seealso{clearvars, who, whos, exist, mlock}
1233 @end deftypefn */)
1234 {
1235  int argc = args.length () + 1;
1236 
1237  string_vector argv = args.make_argv ("clear");
1238 
1239  if (argc == 1)
1240  {
1241  do_clear_variables (interp, argv, argc, true);
1242 
1243  event_manager& evmgr = interp.get_event_manager ();
1244 
1245  evmgr.clear_workspace ();
1246  }
1247  else
1248  {
1249  int idx = 0;
1250 
1251  bool clear_all = false;
1252  bool clear_functions = false;
1253  bool clear_globals = false;
1254  bool clear_variables = false;
1255  bool clear_objects = false;
1256  bool exclusive = false;
1257  bool have_regexp = false;
1258  bool have_dash_option = false;
1259 
1260  while (++idx < argc)
1261  {
1262  if (argv[idx] == "-all" || argv[idx] == "-a")
1263  {
1264  if (have_dash_option)
1265  print_usage ();
1266 
1267  have_dash_option = true;
1268  clear_all = true;
1269  }
1270  else if (argv[idx] == "-exclusive" || argv[idx] == "-x")
1271  {
1272  exclusive = true;
1273  }
1274  else if (argv[idx] == "-functions" || argv[idx] == "-f")
1275  {
1276  if (have_dash_option)
1277  print_usage ();
1278 
1279  have_dash_option = true;
1280  clear_functions = true;
1281  }
1282  else if (argv[idx] == "-global" || argv[idx] == "-g")
1283  {
1284  if (have_dash_option)
1285  print_usage ();
1286 
1287  have_dash_option = true;
1288  clear_globals = true;
1289  }
1290  else if (argv[idx] == "-variables" || argv[idx] == "-v")
1291  {
1292  if (have_dash_option)
1293  print_usage ();
1294 
1295  have_dash_option = true;
1296  clear_variables = true;
1297  }
1298  else if (argv[idx] == "-classes" || argv[idx] == "-c")
1299  {
1300  if (have_dash_option)
1301  print_usage ();
1302 
1303  have_dash_option = true;
1304  clear_objects = true;
1305  }
1306  else if (argv[idx] == "-regexp" || argv[idx] == "-r")
1307  {
1308  if (have_dash_option)
1309  print_usage ();
1310 
1311  have_dash_option = true;
1312  have_regexp = true;
1313  }
1314  else
1315  break;
1316  }
1317 
1318  if (idx <= argc)
1319  {
1320  if (! have_dash_option && ! exclusive)
1321  do_matlab_compatible_clear (interp, argv, argc, idx);
1322  else
1323  {
1324  if (clear_all)
1325  {
1326  maybe_warn_exclusive (exclusive);
1327 
1328  if (++idx < argc)
1329  warning ("clear: ignoring extra arguments after -all");
1330 
1331  interp.clear_all ();
1332  }
1333  else if (have_regexp)
1334  {
1335  do_clear_variables (interp, argv, argc, idx, exclusive, true);
1336  }
1337  else if (clear_functions)
1338  {
1339  do_clear_functions (interp, argv, argc, idx, exclusive);
1340  }
1341  else if (clear_globals)
1342  {
1343  do_clear_globals (interp, argv, argc, idx, exclusive);
1344  }
1345  else if (clear_variables)
1346  {
1347  do_clear_variables (interp, argv, argc, idx, exclusive);
1348  }
1349  else if (clear_objects)
1350  {
1351  interp.clear_objects ();
1353  interp.clear_all ();
1354  }
1355  else
1356  {
1357  do_clear_symbols (interp, argv, argc, idx, exclusive);
1358  }
1359  }
1360  }
1361  }
1362 
1363  return ovl ();
1364 }
1365 
1366 /*
1367 ## This test must be wrapped in its own function or the 'clear' command will
1368 ## break the %!test environment.
1369 %!function __test_clear_no_args__ ()
1370 %! global x;
1371 %! x = 3;
1372 %! clear
1373 %! assert (! exist ("x", "var")); # x is not in the current workspace anymore
1374 %! global x; # but still lives in the global workspace
1375 %! assert (exist ("x", "var"));
1376 %!endfunction
1377 
1378 %!test
1379 %! unwind_protect
1380 %! __test_clear_no_args__ ();
1381 %! unwind_protect_cleanup
1382 %! clear -g x
1383 %! end_unwind_protect
1384 
1385 ## Test that multiple options cannot be given
1386 %!error clear -f -g
1387 */
1388 
1389 static std::string Vmissing_function_hook = "__unimplemented__";
1390 
1391 DEFUN (missing_function_hook, args, nargout,
1392  doc: /* -*- texinfo -*-
1393 @deftypefn {} {@var{val} =} missing_function_hook ()
1394 @deftypefnx {} {@var{old_val} =} missing_function_hook (@var{new_val})
1395 @deftypefnx {} {@var{old_val} =} missing_function_hook (@var{new_val}, "local")
1396 Query or set the internal variable that specifies the function to call
1397 to provide extra information when an unknown identifier is referenced.
1398 
1399 When called from inside a function with the @qcode{"local"} option, the
1400 variable is changed locally for the function and any subroutines it calls.
1401 The original variable value is restored when exiting the function.
1402 @seealso{missing_component_hook}
1403 @end deftypefn */)
1404 {
1405  return set_internal_variable (Vmissing_function_hook, args, nargout,
1406  "missing_function_hook");
1407 }
1408 
1409 std::string
1410 maybe_missing_function_hook (const std::string& name)
1411 {
1412  octave::interpreter& interp = octave::__get_interpreter__ ();
1413 
1414  // Don't do this if we're handling errors.
1415  if (Vmissing_function_hook.empty ())
1416  return "";
1417 
1418  octave::symbol_table& symtab = interp.get_symbol_table ();
1419 
1420  octave_value val = symtab.find_function (Vmissing_function_hook);
1421 
1422  if (val.is_defined ())
1423  {
1424  // Ensure auto-restoration.
1425  octave::unwind_protect_var<std::string>
1426  restore_var (Vmissing_function_hook);
1427 
1428  // Clear the variable prior to calling the function.
1429  const std::string fcn_name = Vmissing_function_hook;
1430  Vmissing_function_hook.clear ();
1431 
1432  // Call.
1433  octave_value_list tmp = octave::feval (fcn_name, octave_value (name), 1);
1434 
1435  if (tmp.length () == 1 && tmp(0).is_string ())
1436  return tmp(0).string_value ();
1437  }
1438 
1439  return "";
1440 }
1441 
1442 DEFMETHOD (__varval__, interp, args, ,
1443  doc: /* -*- texinfo -*-
1444 @deftypefn {} {@var{value} =} __varval__ (@var{name})
1445 Return the value of the variable @var{name} directly from the symbol table.
1446 
1447 If @var{name} does not exist then nothing is returned, not even an empty matrix
1448 (@code{[]}), since there would be no way to distinguish between a variable
1449 not found in the symbol table and a variable who's value was @code{[]}.
1450 
1451 A standard usage pattern is to code a @code{try}/@code{catch} block around a
1452 call to @code{__varval__}.
1453 
1454 Example Code
1455 
1456 @example
1457 @group
1458 try
1459  @var{val} = __varval__ (@var{name});
1460 catch
1461  ## No variable @var{name} found in symbol table
1462  @var{val} = NA; # Substitute Not Available (NA)
1463  error ("@var{name} not found"); # or, throw an error.
1464 end_try_catch
1465 @end group
1466 @end example
1467 
1468 Programming Note: The magic @var{name} @qcode{".argn."} will retrieve the text
1469 of input arguments to a function and is used by @code{inputname} internally.
1470 @seealso{inputname}
1471 @end deftypefn */)
1472 {
1473  if (args.length () != 1)
1474  print_usage ();
1475 
1476  std::string name = args(0).xstring_value ("__varval__: NAME must be a string");
1477 
1478  // We need this kluge to implement inputname in a .m file.
1479  if (name == ".argn.")
1480  {
1481  tree_evaluator& tw = interp.get_evaluator ();
1482 
1484  }
1485 
1486  return interp.varval (name);
1487 }
1488 
1489 static std::string Vmissing_component_hook;
1490 
1491 DEFUN (missing_component_hook, args, nargout,
1492  doc: /* -*- texinfo -*-
1493 @deftypefn {} {@var{val} =} missing_component_hook ()
1494 @deftypefnx {} {@var{old_val} =} missing_component_hook (@var{new_val})
1495 @deftypefnx {} {@var{old_val} =} missing_component_hook (@var{new_val}, "local")
1496 Query or set the internal variable that specifies the function to call when
1497 a component of Octave is missing.
1498 
1499 This can be useful for packagers that may split the Octave installation into
1500 multiple sub-packages, for example, to provide a hint to users for how to
1501 install the missing components.
1502 
1503 When called from inside a function with the @qcode{"local"} option, the
1504 variable is changed locally for the function and any subroutines it calls.
1505 The original variable value is restored when exiting the function.
1506 
1507 The hook function is expected to be of the form
1508 
1509 @example
1510 @var{fcn} (@var{component})
1511 @end example
1512 
1513 Octave will call @var{fcn} with the name of the function that requires the
1514 component and a string describing the missing component. The hook function
1515 should return an error message to be displayed.
1516 @seealso{missing_function_hook}
1517 @end deftypefn */)
1518 {
1519  return set_internal_variable (Vmissing_component_hook, args, nargout,
1520  "missing_component_hook");
1521 }
1522 
OCTAVE_END_NAMESPACE(octave)
Provides threadsafe access to octave.
void clear_workspace(void)
bool match(const std::string &str) const
Definition: glob-match.cc:35
octave_value varval(const std::string &name) const
void clear_variable(const std::string &name)
void clear_variables(void)
tree_evaluator & get_evaluator(void)
void clear_symbol_pattern(const std::string &pat)
void clear_global_variable(const std::string &name)
void clear_global_variable_pattern(const std::string &pattern)
void clear_objects(void)
std::list< std::string > global_variable_names(void)
void clear_variable_regexp(const std::string &pattern)
symbol_table & get_symbol_table(void)
Definition: interpreter.h:298
void clear_variable_pattern(const std::string &pattern)
void clear_function_pattern(const std::string &pat)
bool is_local_variable(const std::string &name) const
std::list< std::string > variable_names(void)
void clear_function(const std::string &name)
std::list< std::string > user_function_names(void)
void clear_all(bool force=false)
load_path & get_load_path(void)
Definition: interpreter.h:283
void clear_functions(bool force=false)
std::string find_fcn(const std::string &fcn, std::string &dir_name, const std::string &pack_name="")
Definition: load-path.h:111
std::string find_method(const std::string &class_name, const std::string &meth, std::string &dir_name, const std::string &pack_name="")
Definition: load-path.h:79
static OCTINTERP_API void clear_exemplar_map(void)
Definition: ov-class.cc:1099
octave_idx_type length(void) const
Definition: ovl.h:113
OCTINTERP_API octave_function * function_value(bool silent=false) const
bool is_constant(void) const
Definition: ov.h:810
bool is_string(void) const
Definition: ov.h:682
bool is_defined(void) const
Definition: ov.h:637
bool is_function_handle(void) const
Definition: ov.h:813
bool is_classdef_meta(void) const
Definition: ov.h:697
std::string string_value(bool force=false) const
Definition: ov.h:1019
bool is_anonymous_function(void) const
Definition: ov.h:816
bool isobject(void) const
Definition: ov.h:709
bool is_inline_function(void) const
Definition: ov.h:819
bool is_match(const std::string &buffer) const
Definition: lo-regexp.cc:580
bool is_built_in_function_name(const std::string &name)
Definition: symtab.cc:67
octave_value find_function(const std::string &name, const symbol_scope &search_scope=symbol_scope())
Definition: symtab.cc:249
octave_value find_cmdline_function(const std::string &name)
Definition: symtab.cc:310
octave_value get_auto_fcn_var(stack_frame::auto_var_type avt) const
Definition: pt-eval.cc:2205
std::string lookup_autoload(const std::string &nm) const
Definition: pt-eval.cc:4604
OCTAVE_BEGIN_NAMESPACE(octave) static octave_value daspk_fcn
OCTINTERP_API void print_usage(void)
Definition: defun-int.h:72
#define DEFMETHOD(name, interp_name, args_name, nargout_name, doc)
Macro to define a builtin method.
Definition: defun.h:111
#define DEFUN(name, args_name, nargout_name, doc)
Macro to define a builtin function.
Definition: defun.h:56
void warning(const char *fmt,...)
Definition: error.cc:1054
void error_with_cfn(const char *fmt,...)
Definition: error.cc:1009
void error(const char *fmt,...)
Definition: error.cc:979
void error_unless(bool cond)
Definition: error.h:549
interpreter & __get_interpreter__(void)
symbol_table & __get_symbol_table__(void)
tree_evaluator & __get_evaluator__(void)
bool iskeyword(const std::string &s)
Definition: lex.cc:1359
static std::string basename(const std::string &s, bool strip_path=false)
octave_value_list feval(const char *name, const octave_value_list &args, int nargout)
Evaluate an Octave function (built-in or interpreted) and return the list of result values.
Definition: oct-parse.cc:10370
@ btyp_unknown
Definition: ov-base.h:101
octave_value_list ovl(const OV_Args &... args)
Construct an octave_value_list with less typing.
Definition: ovl.h:211
bool drive_or_unc_share(const std::string &name)
Definition: sysdep.cc:460
std::string file_in_path(const std::string &name, const std::string &suffix)
Definition: utils.cc:691
octave_value set_internal_variable(bool &var, const octave_value_list &args, int nargout, const char *nm)
Definition: variables.cc:584
#define GET_IDX(LEN)
Definition: variables.cc:336
static void do_clear_symbols(interpreter &interp, const string_vector &argv, int argc, int idx, bool exclusive=false)
Definition: variables.cc:1076
static void do_clear_functions(interpreter &interp, const string_vector &argv, int argc, int idx, bool exclusive=false)
Definition: variables.cc:974
static bool try_local_protect(T &var)
Definition: variables.cc:570
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:932
static void do_clear_variables(interpreter &interp, const string_vector &argv, int argc, int idx, bool exclusive=false, bool have_regexp=false)
Definition: variables.cc:1044
static octave::unwind_protect * curr_fcn_unwind_protect_frame(void)
Definition: variables.cc:561
static void do_clear_globals(interpreter &interp, const string_vector &argv, int argc, int idx, bool exclusive=false)
Definition: variables.cc:1001
static int symbol_exist(interpreter &interp, const std::string &name, const std::string &type="any")
Definition: variables.cc:161
static void do_matlab_compatible_clear(interpreter &interp, const string_vector &argv, int argc, int idx)
Definition: variables.cc:1105
std::string maybe_missing_function_hook(const std::string &name)
Definition: variables.cc:1410
octave_function * is_valid_function(const std::string &fcn_name, const std::string &warn_for, bool warn)
Definition: variables.cc:77
std::string unique_symbol_name(const std::string &basename)
Definition: variables.cc:340
static bool wants_local_change(const octave_value_list &args, int &nargin)
Definition: variables.cc:544
static std::string Vmissing_function_hook
Definition: variables.cc:1389
static void maybe_warn_exclusive(bool exclusive)
Definition: variables.cc:967
static std::string Vmissing_component_hook
Definition: variables.cc:1489
F77_RET_T len
Definition: xerbla.cc:61