3Copyright (C) 1993, 1994, 1995, 1996, 1997, 1998, 1999, 2000, 2001,
4 2002, 2003, 2004, 2005, 2006, 2007, 2008, 2009 John W. Eaton
6This file is part of Octave.
8Octave is free software; you can redistribute it and/or modify it
9under the terms of the GNU General Public License as published by the
10Free Software Foundation; either version 3 of the License, or (at your
11option) any later version.
13Octave is distributed in the hope that it will be useful, but WITHOUT
14ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
15FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
18You should have received a copy of the GNU General Public License
19along with Octave; see the file COPYING. If not, see
20<http://www.gnu.org/licenses/>.
44#include "lo-mappers.h"
47#include "pathsearch.h"
64#include "unwind-prot.h"
68// Return TRUE if S is a valid identifier.
71valid_identifier (const char *s)
73 if (! s || ! (isalpha (*s) || *s == '_' || *s == '$'))
77 if (! (isalnum (*s) || *s == '_' || *s == '$'))
84valid_identifier (const std::string& s)
86 return valid_identifier (s.c_str ());
89DEFUN (isvarname, args, ,
91@deftypefn {Built-in Function} {} isvarname (@var{name})\n\
92Return true if @var{name} is a valid variable name\n\
97 int argc = args.length () + 1;
99 string_vector argv = args.make_argv ("isvarname");
105 retval = valid_identifier (argv[1]);
112// Return TRUE if F and G are both names for the same file.
115same_file (const std::string& f, const std::string& g)
117 return same_file_internal (f, g);
121almost_match (const std::string& std, const std::string& s, int min_match_len,
124 int stdlen = std.length ();
125 int slen = s.length ();
127 return (slen <= stdlen
128 && slen >= min_match_len
130 ? (strncmp (std.c_str (), s.c_str (), slen) == 0)
131 : (octave_strncasecmp (std.c_str (), s.c_str (), slen) == 0)));
137keyword_almost_match (const char * const *std, int *min_len, const std::string& s,
138 int min_toks_to_match, int max_toks)
142 int toks_matched = 0;
144 if (s.empty () || max_toks < 1)
147 char *kw = strsave (s.c_str ());
165 const char **to_match = new const char * [max_toks + 1];
166 const char * const *s1 = std;
167 const char **s2 = to_match;
174 while ((end = strchr (beg, ' ')) != 0)
186 if (tok_count >= max_toks)
197 if (! almost_match (*s1, *s2, min_len[toks_matched], 0))
207 status = (toks_matched >= min_toks_to_match);
223// Return non-zero if either NR or NC is zero. Return -1 if this
224// should be considered fatal; return 1 if this is ok.
227empty_arg (const char * /* name */, octave_idx_type nr, octave_idx_type nc)
229 return (nr == 0 || nc == 0);
232// See if the given file is in the path.
235search_path_for_file (const std::string& path, const string_vector& names)
239 return octave_env::make_absolute (p.find_first_of (names));
242// Find all locations of the given file in the path.
245search_path_for_all_files (const std::string& path, const string_vector& names)
249 string_vector sv = p.find_all_first_of (names);
251 octave_idx_type len = sv.length ();
253 for (octave_idx_type i = 0; i < len; i++)
254 sv[i] = octave_env::make_absolute (sv[i]);
260make_absolute (const string_vector& sv)
262 octave_idx_type len = sv.length ();
264 string_vector retval (len);
266 for (octave_idx_type i = 0; i < len; i++)
267 retval[i] = octave_env::make_absolute (sv[i]);
272DEFUN (file_in_loadpath, args, ,
274@deftypefn {Built-in Function} {} file_in_loadpath (@var{file})\n\
275@deftypefnx {Built-in Function} {} file_in_loadpath (@var{file}, \"all\")\n\
277Return the absolute name of @var{file} if it can be found in\n\
278the list of directories specified by @code{path}.\n\
279If no file is found, return an empty matrix.\n\
281If the first argument is a cell array of strings, search each\n\
282directory of the loadpath for element of the cell array and return\n\
283the first that matches.\n\
285If the second optional argument @code{\"all\"} is supplied, return\n\
286a cell array containing the list of all files that have the same\n\
287name in the path. If no files are found, return an empty cell array.\n\
288@seealso{file_in_path, path}\n\
293 int nargin = args.length ();
295 if (nargin == 1 || nargin == 2)
297 string_vector names = args(0).all_strings ();
299 if (! error_state && names.length () > 0)
304 = octave_env::make_absolute (load_path::find_first_of (names));
311 else if (nargin == 2)
313 std::string opt = args(1).string_value ();
315 if (! error_state && opt == "all")
316 retval = Cell (make_absolute
317 (load_path::find_all_first_of (names)));
319 error ("file_in_loadpath: invalid option");
323 error ("file_in_loadpath: expecting string as first argument");
331DEFUN (file_in_path, args, ,
333@deftypefn {Built-in Function} {} file_in_path (@var{path}, @var{file})\n\
334@deftypefnx {Built-in Function} {} file_in_path (@var{path}, @var{file}, \"all\")\n\
335Return the absolute name of @var{file} if it can be found in\n\
336@var{path}. The value of @var{path} should be a colon-separated list of\n\
337directories in the format described for @code{path}. If no file\n\
338is found, return an empty matrix. For example,\n\
342file_in_path (EXEC_PATH, \"sh\")\n\
343 @result{} \"/bin/sh\"\n\
347If the second argument is a cell array of strings, search each\n\
348directory of the path for element of the cell array and return\n\
349the first that matches.\n\
351If the third optional argument @code{\"all\"} is supplied, return\n\
352a cell array containing the list of all files that have the same\n\
353name in the path. If no files are found, return an empty cell array.\n\
354@seealso{file_in_loadpath}\n\
359 int nargin = args.length ();
361 if (nargin == 2 || nargin == 3)
363 std::string path = args(0).string_value ();
367 string_vector names = args(1).all_strings ();
369 if (! error_state && names.length () > 0)
373 std::string fname = search_path_for_file (path, names);
380 else if (nargin == 3)
382 std::string opt = args(2).string_value ();
384 if (! error_state && opt == "all")
385 retval = Cell (make_absolute
386 (search_path_for_all_files (path, names)));
388 error ("file_in_path: invalid option");
392 error ("file_in_path: expecting string as second argument");
395 error ("file_in_path: expecting string as first argument");
404file_in_path (const std::string& name, const std::string& suffix)
406 std::string nm = name;
408 if (! suffix.empty ())
411 return octave_env::make_absolute (load_path::find_file (nm));
414// See if there is an function file in the path. If so, return the
415// full path to the file.
418fcn_file_in_path (const std::string& name)
422 int len = name.length ();
426 if (octave_env::absolute_pathname (name))
433 else if (len > 2 && name [len - 2] == '.' && name [len - 1] == 'm')
434 retval = load_path::find_fcn_file (name.substr (0, len-2));
437 std::string fname = name;
438 size_t pos = name.find_first_of (Vfilemarker);
439 if (pos != std::string::npos)
440 fname = name.substr (0, pos);
442 retval = load_path::find_fcn_file (fname);
449// See if there is a directory called "name" in the path and if it
450// contains a Contents.m file return the full path to this file.
453contents_file_in_path (const std::string& dir)
457 if (dir.length () > 0)
459 std::string tcontents = file_ops::concat (load_path::find_dir (dir),
460 std::string ("Contents.m"));
462 file_stat fs (tcontents);
465 retval = octave_env::make_absolute (tcontents);
471// See if there is a .oct file in the path. If so, return the
472// full path to the file.
475oct_file_in_path (const std::string& name)
479 int len = name.length ();
483 if (octave_env::absolute_pathname (name))
490 else if (len > 4 && name [len - 4] == '.' && name [len - 3] == 'o'
491 && name [len - 2] == 'c' && name [len - 1] == 't')
492 retval = load_path::find_oct_file (name.substr (0, len-4));
494 retval = load_path::find_oct_file (name);
500// See if there is a .mex file in the path. If so, return the
501// full path to the file.
504mex_file_in_path (const std::string& name)
508 int len = name.length ();
512 if (octave_env::absolute_pathname (name))
519 else if (len > 4 && name [len - 4] == '.' && name [len - 3] == 'm'
520 && name [len - 2] == 'e' && name [len - 1] == 'x')
521 retval = load_path::find_mex_file (name.substr (0, len-4));
523 retval = load_path::find_mex_file (name);
529// Replace backslash escapes in a string with the real values.
532do_string_escapes (const std::string& s)
538 size_t len = s.length ();
544 if (s[j] == '\\' && j+1 < len)
556 case 'b': // backspace
560 case 'f': // formfeed
568 case 'r': // carriage return
572 case 't': // horizontal tab
576 case 'v': // vertical tab
580 case '\\': // backslash
588 case '"': // double quote
593 warning ("unrecognized escape sequence `\\%c' --\
594 converting to `%c'", s[j], s[j]);
613DEFUN (do_string_escapes, args, ,
615@deftypefn {Built-in Function} {} do_string_escapes (@var{string})\n\
616Convert special characters in @var{string} to their escaped forms.\n\
621 int nargin = args.length ();
625 if (args(0).is_string ())
626 retval = do_string_escapes (args(0).string_value ());
628 error ("do_string_escapes: argument must be a string");
637undo_string_escape (char c)
650 case '\b': // backspace
653 case '\f': // formfeed
656 case '\n': // newline
659 case '\r': // carriage return
662 case '\t': // horizontal tab
665 case '\v': // vertical tab
668 case '\\': // backslash
671 case '"': // double quote
676 static char retval[2];
685undo_string_escapes (const std::string& s)
689 for (size_t i = 0; i < s.length (); i++)
690 retval.append (undo_string_escape (s[i]));
695DEFUN (undo_string_escapes, args, ,
697@deftypefn {Built-in Function} {} undo_string_escapes (@var{s})\n\
698Converts special characters in strings back to their escaped forms. For\n\
699example, the expression\n\
706assigns the value of the alert character (control-g, ASCII code 7) to\n\
707the string variable @code{bell}. If this string is printed, the\n\
708system will ring the terminal bell (if it is possible). This is\n\
709normally the desired outcome. However, sometimes it is useful to be\n\
710able to print the original representation of the string, with the\n\
711special characters replaced by their escape sequences. For example,\n\
715octave:13> undo_string_escapes (bell)\n\
721replaces the unprintable alert character with its printable\n\
727 int nargin = args.length ();
731 if (args(0).is_string ())
732 retval = undo_string_escapes (args(0).string_value ());
734 error ("undo_string_escapes: argument must be a string");
742DEFUN (is_absolute_filename, args, ,
744@deftypefn {Built-in Function} {} is_absolute_filename (@var{file})\n\
745Return true if @var{file} is an absolute filename.\n\
748 octave_value retval = false;
750 if (args.length () == 1)
751 retval = (args(0).is_string ()
752 && octave_env::absolute_pathname (args(0).string_value ()));
759DEFUN (is_rooted_relative_filename, args, ,
761@deftypefn {Built-in Function} {} is_rooted_relative_filename (@var{file})\n\
762Return true if @var{file} is a rooted-relative filename.\n\
765 octave_value retval = false;
767 if (args.length () == 1)
768 retval = (args(0).is_string ()
769 && octave_env::rooted_relative_pathname (args(0).string_value ()));
776DEFUN (make_absolute_filename, args, ,
778@deftypefn {Built-in Function} {} make_absolute_filename (@var{file})\n\
779Return the full name of @var{file}, relative to the current directory.\n\
782 octave_value retval = std::string ();
784 if (args.length () == 1)
786 std::string nm = args(0).string_value ();
789 retval = octave_env::make_absolute (nm);
791 error ("make_absolute_filename: expecting argument to be a file name");
799DEFUN (find_dir_in_path, args, ,
801@deftypefn {Built-in Function} {} find_dir_in_path (@var{dir}, \"all\")\n\
802Return the full name of the path element matching @var{dir}. The\n\
803match is performed at the end of each path element. For example, if\n\
804@var{dir} is @code{\"foo/bar\"}, it matches the path element\n\
805@code{\"/some/dir/foo/bar\"}, but not @code{\"/some/dir/foo/bar/baz\"}\n\
806or @code{\"/some/dir/allfoo/bar\"}.\n\
808The second argument is optional. If it is supplied, return a cell array\n\
809containing all the directory names that match.\n\
812 octave_value retval = std::string ();
814 int nargin = args.length ();
818 if (nargin == 1 || nargin == 2)
820 dir = args(0).string_value ();
825 retval = load_path::find_dir (dir);
826 else if (nargin == 2)
827 retval = Cell (load_path::find_matching_dirs (dir));
830 error ("find_dir_in_path: expecting argument to be a directory name");
838DEFUNX ("errno", Ferrno, args, ,
840@deftypefn {Built-in Function} {@var{err} =} errno ()\n\
841@deftypefnx {Built-in Function} {@var{err} =} errno (@var{val})\n\
842@deftypefnx {Built-in Function} {@var{err} =} errno (@var{name})\n\
843Return the current value of the system-dependent variable errno,\n\
844set its value to @var{val} and return the previous value, or return\n\
845the named error code given @var{name} as a character string, or -1\n\
846if @var{name} is not found.\n\
851 int nargin = args.length ();
855 if (args(0).is_string ())
857 std::string nm = args(0).string_value ();
860 retval = octave_errno::lookup (nm);
862 error ("errno: expecting character string argument");
866 int val = args(0).int_value ();
869 retval = octave_errno::set (val);
871 error ("errno: expecting integer argument");
874 else if (nargin == 0)
875 retval = octave_errno::get ();
882DEFUN (errno_list, args, ,
884@deftypefn {Built-in Function} {} errno_list ()\n\
885Return a structure containing the system-dependent errno values.\n\
890 if (args.length () == 0)
891 retval = octave_errno::list ();
899check_dimensions (octave_idx_type& nr, octave_idx_type& nc, const char *warnfor)
901 if (nr < 0 || nc < 0)
903 warning_with_id ("Octave:neg-dim-as-zero",
904 "%s: converting negative dimension to zero", warnfor);
906 nr = (nr < 0) ? 0 : nr;
907 nc = (nc < 0) ? 0 : nc;
912check_dimensions (dim_vector& dim, const char *warnfor)
916 for (int i = 0; i < dim.length (); i++)
926 warning_with_id ("Octave:neg-dim-as-zero",
927 "%s: converting negative dimension to zero", warnfor);
932get_dimensions (const octave_value& a, const char *warn_for,
935 if (a.is_scalar_type ())
938 dim(0) = a.int_value ();
943 octave_idx_type nr = a.rows ();
944 octave_idx_type nc = a.columns ();
946 if (nr == 1 || nc == 1)
948 Array<double> v = a.vector_value ();
953 octave_idx_type n = v.length ();
955 for (octave_idx_type i = 0; i < n; i++)
956 dim(i) = static_cast<int> (fix (v(i)));
959 error ("%s (A): use %s (size (A)) instead", warn_for, warn_for);
963 check_dimensions (dim, warn_for); // May set error_state.
968get_dimensions (const octave_value& a, const char *warn_for,
969 octave_idx_type& nr, octave_idx_type& nc)
971 if (a.is_scalar_type ())
973 nr = nc = a.int_value ();
980 if ((nr == 1 && nc == 2) || (nr == 2 && nc == 1))
982 Array<double> v = a.vector_value ();
987 nr = static_cast<octave_idx_type> (fix (v (0)));
988 nc = static_cast<octave_idx_type> (fix (v (1)));
991 error ("%s (A): use %s (size (A)) instead", warn_for, warn_for);
995 check_dimensions (nr, nc, warn_for); // May set error_state.
999get_dimensions (const octave_value& a, const octave_value& b,
1000 const char *warn_for, octave_idx_type& nr, octave_idx_type& nc)
1002 nr = a.is_empty () ? 0 : a.int_value ();
1003 nc = b.is_empty () ? 0 : b.int_value ();
1006 error ("%s: expecting two scalar arguments", warn_for);
1008 check_dimensions (nr, nc, warn_for); // May set error_state.
1012dims_to_numel (const dim_vector& dims, const octave_value_list& idx)
1014 octave_idx_type retval;
1016 octave_idx_type len = idx.length ();
1019 retval = dims.numel ();
1022 const dim_vector dv = dims.redim (len);
1024 for (octave_idx_type i = 0; i < len; i++)
1026 octave_value idxi = idx(i);
1027 if (idxi.is_magic_colon ())
1029 else if (idxi.is_numeric_type ())
1030 retval *= idxi.numel ();
1033 idx_vector jdx = idxi.index_vector ();
1036 retval *= jdx.length (dv(i));
1045decode_subscripts (const char* name, const octave_value& arg,
1046 std::string& type_string,
1047 std::list<octave_value_list>& idx)
1049 Octave_map m = arg.map_value ();
1052 && m.nfields () == 2 && m.contains ("type") && m.contains ("subs"))
1054 Cell& type = m.contents ("type");
1055 Cell& subs = m.contents ("subs");
1057 type_string = std::string (type.length(), '\0');
1059 for (int k = 0; k < type.length (); k++)
1061 std::string item = type(k).string_value ();
1066 type_string[k] = '{';
1067 else if (item == "()")
1068 type_string[k] = '(';
1069 else if (item == ".")
1070 type_string[k] = '.';
1073 error("%s: invalid indexing type `%s'", name, item.c_str ());
1079 error ("%s: expecting type(%d) to be a character string",
1084 octave_value_list idx_item;
1086 if (subs(k).is_string ())
1087 idx_item(0) = subs(k);
1088 else if (subs(k).is_cell ())
1090 Cell subs_cell = subs(k).cell_value ();
1092 for (int n = 0; n < subs_cell.length (); n++)
1094 if (subs_cell(n).is_string ()
1095 && subs_cell(n).string_value () == ":")
1096 idx_item(n) = octave_value(octave_value::magic_colon_t);
1098 idx_item(n) = subs_cell(n);
1103 error ("%s: expecting subs(%d) to be a character string or cell array",
1108 idx.push_back (idx_item);
1112 error ("%s: second argument must be a structure with fields `type' and `subs'", name);
1116identity_matrix (octave_idx_type nr, octave_idx_type nc)
1118 Matrix m (nr, nc, 0.0);
1120 if (nr > 0 && nc > 0)
1122 octave_idx_type n = std::min (nr, nc);
1124 for (octave_idx_type i = 0; i < n; i++)
1132float_identity_matrix (octave_idx_type nr, octave_idx_type nc)
1134 FloatMatrix m (nr, nc, 0.0);
1136 if (nr > 0 && nc > 0)
1138 octave_idx_type n = std::min (nr, nc);
1140 for (octave_idx_type i = 0; i < n; i++)
1148octave_format (std::ostream& os, const char *fmt, ...)
1153 va_start (args, fmt);
1155 retval = octave_vformat (os, fmt, args);
1163octave_vformat (std::ostream& os, const char *fmt, va_list args)
1167#if defined (__GNUG__) && !CXX_ISO_COMPLIANT_LIBRARY
1169 std::streambuf *sb = os.rdbuf ();
1173 BEGIN_INTERRUPT_IMMEDIATELY_IN_FOREIGN_CODE;
1175 retval = sb->vform (fmt, args);
1177 END_INTERRUPT_IMMEDIATELY_IN_FOREIGN_CODE;
1182 char *s = octave_vsnprintf (fmt, args);
1188 retval = strlen (s);
1196// We manage storage. User should not free it, and its contents are
1197// only valid until next call to vsnprintf.
1199// Interrupts might happen if someone makes a call with something that
1200// will require a very large buffer. If we are interrupted in that
1201// case, we should make the buffer size smaller for the next call.
1203#define BEGIN_INTERRUPT_IMMEDIATELY_IN_FOREIGN_CODE_FOR_VSNPRINTF \
1204 BEGIN_INTERRUPT_IMMEDIATELY_IN_FOREIGN_CODE_1; \
1207 size = initial_size; \
1208 octave_rethrow_exception (); \
1209 BEGIN_INTERRUPT_IMMEDIATELY_IN_FOREIGN_CODE_2
1211#if defined __GNUC__ && defined __va_copy
1212#define SAVE_ARGS(saved_args, args) __va_copy (saved_args, args)
1213#elif defined va_copy
1214#define SAVE_ARGS(saved_args, args) va_copy (saved_args, args)
1216#define SAVE_ARGS(saved_args, args) saved_args = args
1220octave_vsnprintf (const char *fmt, va_list args)
1222 static const size_t initial_size = 100;
1224 static size_t size = initial_size;
1226 static char *buf = 0;
1231 buf = new char [size];
1240 SAVE_ARGS (saved_args, args);
1242 BEGIN_INTERRUPT_IMMEDIATELY_IN_FOREIGN_CODE_FOR_VSNPRINTF;
1244 nchars = octave_raw_vsnprintf (buf, size, fmt, saved_args);
1246 va_end (saved_args);
1248 END_INTERRUPT_IMMEDIATELY_IN_FOREIGN_CODE;
1250 if (nchars > -1 && nchars < size)
1258 buf = new char [size];
1269octave_snprintf (const char *fmt, ...)
1274 va_start (args, fmt);
1276 retval = octave_vsnprintf (fmt, args);
1284octave_sleep (double seconds)
1291 = static_cast<unsigned int> (modf (seconds, &t) * 1000000);
1294 = (t > UINT_MAX) ? UINT_MAX : static_cast<unsigned int> (t);
1296 // Versions of these functions that accept unsigned int args are
1297 // defined in cutils.c.
1299 octave_usleep (usec);
1305DEFUN (isindex, args, ,
1307@deftypefn {Built-in Function} {} isindex (@var{ind}, @var{n})\n\
1308Returns true if @var{ind} is a valid index. Valid indices can be\n\
1309either positive integers (though possibly real data), or logical arrays.\n\
1310If present, @var{n} specifies the extent of the dimension to be indexed.\n\
1311Note that, if possible, the internal conversion result is cached so that\n\
1312subsequent indexing will not perform the checking again.\n\
1315 octave_value retval;
1316 int nargin = args.length ();
1317 octave_idx_type n = 0;
1320 n = args(1).idx_type_value ();
1321 else if (nargin != 1)
1326 unwind_protect frame;
1327 frame.protect_var (error_state);
1328 frame.protect_var (discard_error_messages);
1329 discard_error_messages = true;
1333 idx_vector idx = args(0).index_vector ();
1337 retval = idx.extent (n) <= n;
1344 catch (octave_execution_exception)
1354do_simple_cellfun (octave_value_list (*fun) (const octave_value_list&, int),
1355 const char *fun_name, const octave_value_list& args,
1358 octave_value_list new_args = args, retval;
1359 int nargin = args.length ();
1360 OCTAVE_LOCAL_BUFFER (bool, iscell, nargin);
1361 OCTAVE_LOCAL_BUFFER (Cell, cells, nargin);
1362 OCTAVE_LOCAL_BUFFER (Cell, rcells, nargout);
1364 const Cell *ccells = cells;
1366 octave_idx_type numel = 1;
1367 dim_vector dims (1, 1);
1369 for (int i = 0; i < nargin; i++)
1371 octave_value arg = new_args(i);
1372 iscell[i] = arg.is_cell ();
1375 cells[i] = arg.cell_value ();
1376 octave_idx_type n = ccells[i].numel ();
1380 new_args(i) = ccells[i](0);
1382 else if (numel == 1)
1385 dims = ccells[i].dims ();
1387 else if (dims != ccells[i].dims ())
1389 error ("%s: cell arguments must have matching sizes", fun_name);
1397 for (int i = 0; i < nargout; i++)
1398 rcells[i].clear (dims);
1400 for (octave_idx_type j = 0; j < numel; j++)
1402 for (int i = 0; i < nargin; i++)
1404 new_args(i) = ccells[i](j);
1408 const octave_value_list tmp = fun (new_args, nargout);
1410 if (tmp.length () < nargout)
1412 error ("%s: do_simple_cellfun: internal error", fun_name);
1417 for (int i = 0; i < nargout; i++)
1418 rcells[i](j) = tmp(i);
1425 retval.resize (nargout);
1426 for (int i = 0; i < nargout; i++)
1427 retval(i) = rcells[i];
1434do_simple_cellfun (octave_value_list (*fun) (const octave_value_list&, int),
1435 const char *fun_name, const octave_value_list& args)
1437 octave_value retval;
1438 const octave_value_list tmp = do_simple_cellfun (fun, fun_name, args, 1);
1439 if (tmp.length () > 0)