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/>.
37#ifdef HAVE_SYS_TYPES_H
48#include "lo-mappers.h"
51#include "pathsearch.h"
68#include "unwind-prot.h"
72// Return TRUE if S is a valid identifier.
75valid_identifier (const char *s)
77 if (! s || ! (isalpha (*s) || *s == '_' || *s == '$'))
81 if (! (isalnum (*s) || *s == '_' || *s == '$'))
88valid_identifier (const std::string& s)
90 return valid_identifier (s.c_str ());
93DEFUN (isvarname, args, ,
95@deftypefn {Built-in Function} {} isvarname (@var{name})\n\
96Return true if @var{name} is a valid variable name\n\
101 int argc = args.length () + 1;
103 string_vector argv = args.make_argv ("isvarname");
109 retval = valid_identifier (argv[1]);
116// Return TRUE if F and G are both names for the same file.
119same_file (const std::string& f, const std::string& g)
121 return same_file_internal (f, g);
125almost_match (const std::string& std, const std::string& s, int min_match_len,
128 int stdlen = std.length ();
129 int slen = s.length ();
131 return (slen <= stdlen
132 && slen >= min_match_len
134 ? (strncmp (std.c_str (), s.c_str (), slen) == 0)
135 : (octave_strncasecmp (std.c_str (), s.c_str (), slen) == 0)));
141keyword_almost_match (const char * const *std, int *min_len, const std::string& s,
142 int min_toks_to_match, int max_toks)
146 int toks_matched = 0;
148 if (s.empty () || max_toks < 1)
151 char *kw = strsave (s.c_str ());
169 const char **to_match = new const char * [max_toks + 1];
170 const char * const *s1 = std;
171 const char **s2 = to_match;
178 while ((end = strchr (beg, ' ')) != 0)
190 if (tok_count >= max_toks)
201 if (! almost_match (*s1, *s2, min_len[toks_matched], 0))
211 status = (toks_matched >= min_toks_to_match);
227// Return non-zero if either NR or NC is zero. Return -1 if this
228// should be considered fatal; return 1 if this is ok.
231empty_arg (const char * /* name */, octave_idx_type nr, octave_idx_type nc)
233 return (nr == 0 || nc == 0);
236// See if the given file is in the path.
239search_path_for_file (const std::string& path, const string_vector& names)
243 return octave_env::make_absolute (p.find_first_of (names),
244 octave_env::getcwd ());
247// Find all locations of the given file in the path.
250search_path_for_all_files (const std::string& path, const string_vector& names)
254 string_vector sv = p.find_all_first_of (names);
256 octave_idx_type len = sv.length ();
258 for (octave_idx_type i = 0; i < len; i++)
259 sv[i] = octave_env::make_absolute (sv[i], octave_env::getcwd ());
265make_absolute (const string_vector& sv)
267 octave_idx_type len = sv.length ();
269 string_vector retval (len);
271 for (octave_idx_type i = 0; i < len; i++)
272 retval[i] = octave_env::make_absolute (sv[i], octave_env::getcwd ());
277DEFUN (file_in_loadpath, args, ,
279@deftypefn {Built-in Function} {} file_in_loadpath (@var{file})\n\
280@deftypefnx {Built-in Function} {} file_in_loadpath (@var{file}, \"all\")\n\
282Return the absolute name of @var{file} if it can be found in\n\
283the list of directories specified by @code{path}.\n\
284If no file is found, return an empty matrix.\n\
286If the first argument is a cell array of strings, search each\n\
287directory of the loadpath for element of the cell array and return\n\
288the first that matches.\n\
290If the second optional argument @code{\"all\"} is supplied, return\n\
291a cell array containing the list of all files that have the same\n\
292name in the path. If no files are found, return an empty cell array.\n\
293@seealso{file_in_path, path}\n\
298 int nargin = args.length ();
300 if (nargin == 1 || nargin == 2)
302 string_vector names = args(0).all_strings ();
304 if (! error_state && names.length () > 0)
308 std::string fname = octave_env::make_absolute
309 (load_path::find_first_of (names), octave_env::getcwd ());
316 else if (nargin == 2)
318 std::string opt = args(1).string_value ();
320 if (! error_state && opt == "all")
321 retval = Cell (make_absolute (load_path::find_all_first_of (names)));
323 error ("file_in_loadpath: invalid option");
327 error ("file_in_loadpath: expecting string as first argument");
335DEFUN (file_in_path, args, ,
337@deftypefn {Built-in Function} {} file_in_path (@var{path}, @var{file})\n\
338@deftypefnx {Built-in Function} {} file_in_path (@var{path}, @var{file}, \"all\")\n\
339Return the absolute name of @var{file} if it can be found in\n\
340@var{path}. The value of @var{path} should be a colon-separated list of\n\
341directories in the format described for @code{path}. If no file\n\
342is found, return an empty matrix. For example,\n\
346file_in_path (EXEC_PATH, \"sh\")\n\
347 @result{} \"/bin/sh\"\n\
351If the second argument is a cell array of strings, search each\n\
352directory of the path for element of the cell array and return\n\
353the first that matches.\n\
355If the third optional argument @code{\"all\"} is supplied, return\n\
356a cell array containing the list of all files that have the same\n\
357name in the path. If no files are found, return an empty cell array.\n\
358@seealso{file_in_loadpath}\n\
363 int nargin = args.length ();
365 if (nargin == 2 || nargin == 3)
367 std::string path = args(0).string_value ();
371 string_vector names = args(1).all_strings ();
373 if (! error_state && names.length () > 0)
377 std::string fname = search_path_for_file (path, names);
384 else if (nargin == 3)
386 std::string opt = args(2).string_value ();
388 if (! error_state && opt == "all")
389 retval = Cell (make_absolute (search_path_for_all_files (path, names)));
391 error ("file_in_path: invalid option");
395 error ("file_in_path: expecting string as second argument");
398 error ("file_in_path: expecting string as first argument");
407file_in_path (const std::string& name, const std::string& suffix)
409 std::string nm = name;
411 if (! suffix.empty ())
414 return octave_env::make_absolute
415 (load_path::find_file (nm), octave_env::getcwd ());
418// See if there is an function file in the path. If so, return the
419// full path to the file.
422fcn_file_in_path (const std::string& name)
426 int len = name.length ();
430 if (octave_env::absolute_pathname (name))
437 else if (len > 2 && name [len - 2] == '.' && name [len - 1] == 'm')
438 retval = load_path::find_fcn_file (name.substr (0, len-2));
441 std::string fname = name;
442 size_t pos = name.find_first_of (Vfilemarker);
443 if (pos != std::string::npos)
444 fname = name.substr (0, pos);
446 retval = load_path::find_fcn_file (fname);
453// See if there is a directory called "name" in the path and if it
454// contains a Contents.m file return the full path to this file.
457contents_file_in_path (const std::string& dir)
461 if (dir.length () > 0)
463 std::string tcontents = file_ops::concat (load_path::find_dir (dir),
464 std::string ("Contents.m"));
466 file_stat fs (tcontents);
469 retval = octave_env::make_absolute (tcontents, octave_env::getcwd ());
475// See if there is a .oct file in the path. If so, return the
476// full path to the file.
479oct_file_in_path (const std::string& name)
483 int len = name.length ();
487 if (octave_env::absolute_pathname (name))
494 else if (len > 4 && name [len - 4] == '.' && name [len - 3] == 'o'
495 && name [len - 2] == 'c' && name [len - 1] == 't')
496 retval = load_path::find_oct_file (name.substr (0, len-4));
498 retval = load_path::find_oct_file (name);
504// See if there is a .mex file in the path. If so, return the
505// full path to the file.
508mex_file_in_path (const std::string& name)
512 int len = name.length ();
516 if (octave_env::absolute_pathname (name))
523 else if (len > 4 && name [len - 4] == '.' && name [len - 3] == 'm'
524 && name [len - 2] == 'e' && name [len - 1] == 'x')
525 retval = load_path::find_mex_file (name.substr (0, len-4));
527 retval = load_path::find_mex_file (name);
533// Replace backslash escapes in a string with the real values.
536do_string_escapes (const std::string& s)
542 size_t len = s.length ();
548 if (s[j] == '\\' && j+1 < len)
560 case 'b': // backspace
564 case 'f': // formfeed
572 case 'r': // carriage return
576 case 't': // horizontal tab
580 case 'v': // vertical tab
584 case '\\': // backslash
592 case '"': // double quote
597 warning ("unrecognized escape sequence `\\%c' --\
598 converting to `%c'", s[j], s[j]);
617DEFUN (do_string_escapes, args, ,
619@deftypefn {Built-in Function} {} do_string_escapes (@var{string})\n\
620Convert special characters in @var{string} to their escaped forms.\n\
625 int nargin = args.length ();
629 if (args(0).is_string ())
630 retval = do_string_escapes (args(0).string_value ());
632 error ("do_string_escapes: argument must be a string");
641undo_string_escape (char c)
654 case '\b': // backspace
657 case '\f': // formfeed
660 case '\n': // newline
663 case '\r': // carriage return
666 case '\t': // horizontal tab
669 case '\v': // vertical tab
672 case '\\': // backslash
675 case '"': // double quote
680 static char retval[2];
689undo_string_escapes (const std::string& s)
693 for (size_t i = 0; i < s.length (); i++)
694 retval.append (undo_string_escape (s[i]));
699DEFUN (undo_string_escapes, args, ,
701@deftypefn {Built-in Function} {} undo_string_escapes (@var{s})\n\
702Converts special characters in strings back to their escaped forms. For\n\
703example, the expression\n\
710assigns the value of the alert character (control-g, ASCII code 7) to\n\
711the string variable @code{bell}. If this string is printed, the\n\
712system will ring the terminal bell (if it is possible). This is\n\
713normally the desired outcome. However, sometimes it is useful to be\n\
714able to print the original representation of the string, with the\n\
715special characters replaced by their escape sequences. For example,\n\
719octave:13> undo_string_escapes (bell)\n\
725replaces the unprintable alert character with its printable\n\
731 int nargin = args.length ();
735 if (args(0).is_string ())
736 retval = undo_string_escapes (args(0).string_value ());
738 error ("undo_string_escapes: argument must be a string");
746DEFUN (is_absolute_filename, args, ,
748@deftypefn {Built-in Function} {} is_absolute_filename (@var{file})\n\
749Return true if @var{file} is an absolute filename.\n\
752 octave_value retval = false;
754 if (args.length () == 1)
755 retval = (args(0).is_string ()
756 && octave_env::absolute_pathname (args(0).string_value ()));
763DEFUN (is_rooted_relative_filename, args, ,
765@deftypefn {Built-in Function} {} is_rooted_relative_filename (@var{file})\n\
766Return true if @var{file} is a rooted-relative filename.\n\
769 octave_value retval = false;
771 if (args.length () == 1)
772 retval = (args(0).is_string ()
773 && octave_env::rooted_relative_pathname (args(0).string_value ()));
780DEFUN (make_absolute_filename, args, ,
782@deftypefn {Built-in Function} {} make_absolute_filename (@var{file})\n\
783Return the full name of @var{file}, relative to the current directory.\n\
786 octave_value retval = std::string ();
788 if (args.length () == 1)
790 std::string nm = args(0).string_value ();
793 retval = octave_env::make_absolute (nm, octave_env::getcwd ());
795 error ("make_absolute_filename: expecting argument to be a file name");
803DEFUN (find_dir_in_path, args, ,
805@deftypefn {Built-in Function} {} find_dir_in_path (@var{dir}, \"all\")\n\
806Return the full name of the path element matching @var{dir}. The\n\
807match is performed at the end of each path element. For example, if\n\
808@var{dir} is @code{\"foo/bar\"}, it matches the path element\n\
809@code{\"/some/dir/foo/bar\"}, but not @code{\"/some/dir/foo/bar/baz\"}\n\
810or @code{\"/some/dir/allfoo/bar\"}.\n\
812The second argument is optional. If it is supplied, return a cell array\n\
813containing all the directory names that match.\n\
816 octave_value retval = std::string ();
818 int nargin = args.length ();
822 if (nargin == 1 || nargin == 2)
824 dir = args(0).string_value ();
829 retval = load_path::find_dir (dir);
830 else if (nargin == 2)
831 retval = Cell (load_path::find_matching_dirs (dir));
834 error ("find_dir_in_path: expecting argument to be a directory name");
842DEFUNX ("errno", Ferrno, args, ,
844@deftypefn {Built-in Function} {@var{err} =} errno ()\n\
845@deftypefnx {Built-in Function} {@var{err} =} errno (@var{val})\n\
846@deftypefnx {Built-in Function} {@var{err} =} errno (@var{name})\n\
847Return the current value of the system-dependent variable errno,\n\
848set its value to @var{val} and return the previous value, or return\n\
849the named error code given @var{name} as a character string, or -1\n\
850if @var{name} is not found.\n\
855 int nargin = args.length ();
859 if (args(0).is_string ())
861 std::string nm = args(0).string_value ();
864 retval = octave_errno::lookup (nm);
866 error ("errno: expecting character string argument");
870 int val = args(0).int_value ();
873 retval = octave_errno::set (val);
875 error ("errno: expecting integer argument");
878 else if (nargin == 0)
879 retval = octave_errno::get ();
886DEFUN (errno_list, args, ,
888@deftypefn {Built-in Function} {} errno_list ()\n\
889Return a structure containing the system-dependent errno values.\n\
894 if (args.length () == 0)
895 retval = octave_errno::list ();
903check_dimensions (octave_idx_type& nr, octave_idx_type& nc, const char *warnfor)
905 if (nr < 0 || nc < 0)
907 warning_with_id ("Octave:neg-dim-as-zero",
908 "%s: converting negative dimension to zero", warnfor);
910 nr = (nr < 0) ? 0 : nr;
911 nc = (nc < 0) ? 0 : nc;
916check_dimensions (dim_vector& dim, const char *warnfor)
920 for (int i = 0; i < dim.length (); i++)
930 warning_with_id ("Octave:neg-dim-as-zero",
931 "%s: converting negative dimension to zero", warnfor);
936get_dimensions (const octave_value& a, const char *warn_for,
939 if (a.is_scalar_type ())
942 dim(0) = a.int_value ();
947 octave_idx_type nr = a.rows ();
948 octave_idx_type nc = a.columns ();
950 if (nr == 1 || nc == 1)
952 Array<double> v = a.vector_value ();
957 octave_idx_type n = v.length ();
959 for (octave_idx_type i = 0; i < n; i++)
960 dim(i) = static_cast<int> (fix (v(i)));
963 error ("%s (A): use %s (size (A)) instead", warn_for, warn_for);
967 check_dimensions (dim, warn_for); // May set error_state.
972get_dimensions (const octave_value& a, const char *warn_for,
973 octave_idx_type& nr, octave_idx_type& nc)
975 if (a.is_scalar_type ())
977 nr = nc = a.int_value ();
984 if ((nr == 1 && nc == 2) || (nr == 2 && nc == 1))
986 Array<double> v = a.vector_value ();
991 nr = static_cast<octave_idx_type> (fix (v (0)));
992 nc = static_cast<octave_idx_type> (fix (v (1)));
995 error ("%s (A): use %s (size (A)) instead", warn_for, warn_for);
999 check_dimensions (nr, nc, warn_for); // May set error_state.
1003get_dimensions (const octave_value& a, const octave_value& b,
1004 const char *warn_for, octave_idx_type& nr, octave_idx_type& nc)
1006 nr = a.is_empty () ? 0 : a.int_value ();
1007 nc = b.is_empty () ? 0 : b.int_value ();
1010 error ("%s: expecting two scalar arguments", warn_for);
1012 check_dimensions (nr, nc, warn_for); // May set error_state.
1016dims_to_numel (const dim_vector& dims, const octave_value_list& idx)
1018 octave_idx_type retval;
1020 octave_idx_type len = idx.length ();
1023 retval = dims.numel ();
1026 const dim_vector dv = dims.redim (len);
1028 for (octave_idx_type i = 0; i < len; i++)
1030 octave_value idxi = idx(i);
1031 if (idxi.is_magic_colon ())
1033 else if (idxi.is_numeric_type ())
1034 retval *= idxi.numel ();
1037 idx_vector jdx = idxi.index_vector ();
1040 retval *= jdx.length (dv(i));
1049identity_matrix (octave_idx_type nr, octave_idx_type nc)
1051 Matrix m (nr, nc, 0.0);
1053 if (nr > 0 && nc > 0)
1055 octave_idx_type n = std::min (nr, nc);
1057 for (octave_idx_type i = 0; i < n; i++)
1065float_identity_matrix (octave_idx_type nr, octave_idx_type nc)
1067 FloatMatrix m (nr, nc, 0.0);
1069 if (nr > 0 && nc > 0)
1071 octave_idx_type n = std::min (nr, nc);
1073 for (octave_idx_type i = 0; i < n; i++)
1081octave_format (std::ostream& os, const char *fmt, ...)
1086 va_start (args, fmt);
1088 retval = octave_vformat (os, fmt, args);
1096octave_vformat (std::ostream& os, const char *fmt, va_list args)
1100#if defined (__GNUG__) && !CXX_ISO_COMPLIANT_LIBRARY
1102 std::streambuf *sb = os.rdbuf ();
1106 BEGIN_INTERRUPT_IMMEDIATELY_IN_FOREIGN_CODE;
1108 retval = sb->vform (fmt, args);
1110 END_INTERRUPT_IMMEDIATELY_IN_FOREIGN_CODE;
1115 char *s = octave_vsnprintf (fmt, args);
1121 retval = strlen (s);
1129// We manage storage. User should not free it, and its contents are
1130// only valid until next call to vsnprintf.
1132// Interrupts might happen if someone makes a call with something that
1133// will require a very large buffer. If we are interrupted in that
1134// case, we should make the buffer size smaller for the next call.
1136#define BEGIN_INTERRUPT_IMMEDIATELY_IN_FOREIGN_CODE_FOR_VSNPRINTF \
1137 BEGIN_INTERRUPT_IMMEDIATELY_IN_FOREIGN_CODE_1; \
1140 size = initial_size; \
1141 octave_rethrow_exception (); \
1142 BEGIN_INTERRUPT_IMMEDIATELY_IN_FOREIGN_CODE_2
1144#if defined __GNUC__ && defined __va_copy
1145#define SAVE_ARGS(saved_args, args) __va_copy (saved_args, args)
1146#elif defined va_copy
1147#define SAVE_ARGS(saved_args, args) va_copy (saved_args, args)
1149#define SAVE_ARGS(saved_args, args) saved_args = args
1153octave_vsnprintf (const char *fmt, va_list args)
1155 static const size_t initial_size = 100;
1157 static size_t size = initial_size;
1159 static char *buf = 0;
1161#if defined (HAVE_C99_VSNPRINTF)
1168 buf = new char [size];
1173#if defined (HAVE_C99_VSNPRINTF)
1175 // Note that the caller is responsible for calling va_end on args.
1176 // We will do it for saved_args.
1180 SAVE_ARGS (saved_args, args);
1182 BEGIN_INTERRUPT_IMMEDIATELY_IN_FOREIGN_CODE_FOR_VSNPRINTF;
1184 nchars = octave_raw_vsnprintf (buf, size, fmt, args);
1186 END_INTERRUPT_IMMEDIATELY_IN_FOREIGN_CODE;
1194 buf = new char [size];
1198 BEGIN_INTERRUPT_IMMEDIATELY_IN_FOREIGN_CODE_FOR_VSNPRINTF;
1200 octave_raw_vsnprintf (buf, size, fmt, saved_args);
1202 END_INTERRUPT_IMMEDIATELY_IN_FOREIGN_CODE;
1206 va_end (saved_args);
1214 SAVE_ARGS (saved_args, args);
1216 BEGIN_INTERRUPT_IMMEDIATELY_IN_FOREIGN_CODE_FOR_VSNPRINTF;
1218 nchars = octave_raw_vsnprintf (buf, size, fmt, saved_args);
1220 va_end (saved_args);
1222 END_INTERRUPT_IMMEDIATELY_IN_FOREIGN_CODE;
1224 if (nchars > -1 && nchars < size-1)
1232 buf = new char [size];
1245octave_snprintf (const char *fmt, ...)
1250 va_start (args, fmt);
1252 retval = octave_vsnprintf (fmt, args);
1260octave_sleep (double seconds)
1267 = static_cast<unsigned int> (modf (seconds, &t) * 1000000);
1270 = (t > UINT_MAX) ? UINT_MAX : static_cast<unsigned int> (t);
1272 // Versions of these functions that accept unsigned int args are
1273 // defined in cutils.c.
1275 octave_usleep (usec);
1279DEFUN (isindex, args, ,
1281@deftypefn {Built-in Function} {} isindex (@var{ind}, @var{n})\n\
1282Returns true if @var{ind} is a valid index. Valid indices can be\n\
1283either positive integers (though possibly real data), or logical arrays.\n\
1284If present, @var{n} specifies the extent of the dimension to be indexed.\n\
1285Note that, if possible, the internal conversion result is cached so that\n\
1286subsequent indexing will not perform the checking again.\n\
1289 octave_value retval;
1290 int nargin = args.length ();
1291 octave_idx_type n = 0;
1294 n = args(1).idx_type_value ();
1295 else if (nargin != 1)
1300 unwind_protect::frame_id_t uwp = unwind_protect::begin_frame ();
1301 unwind_protect::protect_var (error_state);
1302 unwind_protect::protect_var (discard_error_messages);
1303 discard_error_messages = true;
1307 idx_vector idx = args(0).index_vector ();
1311 retval = idx.extent (n) <= n;
1318 catch (octave_execution_exception)
1323 unwind_protect::run_frame (uwp);
1330;;; Local Variables: ***