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