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