# HG changeset patch # User jwe # Date 1128034183 0 # Node ID 941f0fc6b596be29db8edf5b92ad1e0f3eb2b897 # Parent 04fa51cb7e9083d8b03eb442159c70ea9484ac2b [project @ 2005-09-29 22:46:07 by jwe] diff --git a/liboctave/ChangeLog b/liboctave/ChangeLog --- a/liboctave/ChangeLog +++ b/liboctave/ChangeLog @@ -1,3 +1,17 @@ +2005-09-29 John W. Eaton + + * file-stat.h (file_stat::mode): New function. + + * file-stat.cc (file_stat::is_blk, file_stat::is_chr, + file_stat::is_dir, file_stat::is_fifo, file_stat::is_lnk, + file_stat::is_reg, file_stat::is_sock): New static functions. + * file-stat.h: Provide decls. + +2005-09-28 John W. Eaton + + * file-ops.cc (file_ops::recursive_rmdir): New function. + * file-ops.h: Provide decl. + 2005-09-19 David Bateman * oct-env.cc (octave_env::do_get_home_directory): diff --git a/liboctave/file-ops.cc b/liboctave/file-ops.cc --- a/liboctave/file-ops.cc +++ b/liboctave/file-ops.cc @@ -41,10 +41,13 @@ #include #endif +#include "dir-ops.h" #include "file-ops.h" +#include "file-stat.h" #include "oct-env.h" #include "oct-passwd.h" #include "pathlen.h" +#include "quit.h" #include "statdefs.h" #include "str-vec.h" @@ -312,6 +315,80 @@ return status; } +// And a version that works recursively. + +int +file_ops::recursive_rmdir (const std::string& name) +{ + std::string msg; + return recursive_rmdir (name, msg); +} + +int +file_ops::recursive_rmdir (const std::string& name, std::string& msg) +{ + msg = std::string (); + + int status = 0; + + dir_entry dir (name); + + if (dir) + { + string_vector dirlist = dir.read (); + + for (octave_idx_type i = 0; i < dirlist.length (); i++) + { + OCTAVE_QUIT; + + std::string nm = dirlist[i]; + + // Skip current directory and parent. + if (nm == "." || nm == "..") + continue; + + std::string fullnm = name + file_ops::dir_sep_str + nm; + + // Get info about the file. Don't follow links. + file_stat fs (fullnm, false); + + if (fs) + { + if (fs.is_dir ()) + { + status = recursive_rmdir (fullnm, msg); + + if (status < 0) + break; + } + else + { + status = unlink (fullnm, msg); + + if (status < 0) + break; + } + } + else + { + msg = fs.error (); + break; + } + } + + if (status >= 0) + status = file_ops::rmdir (name, msg); + } + else + { + status = -1; + + msg = dir.error (); + } + + return status; +} + std::string file_ops::canonicalize_file_name (const std::string& name) { diff --git a/liboctave/file-ops.h b/liboctave/file-ops.h --- a/liboctave/file-ops.h +++ b/liboctave/file-ops.h @@ -56,6 +56,9 @@ static int rmdir (const std::string&); static int rmdir (const std::string&, std::string&); + static int recursive_rmdir (const std::string&); + static int recursive_rmdir (const std::string&, std::string&); + static std::string canonicalize_file_name (const std::string&); static std::string canonicalize_file_name (const std::string&, std::string&); diff --git a/liboctave/file-stat.cc b/liboctave/file-stat.cc --- a/liboctave/file-stat.cc +++ b/liboctave/file-stat.cc @@ -53,68 +53,110 @@ bool file_stat::is_blk (void) const { -#ifdef S_ISBLK - return S_ISBLK (fs_mode); -#else - return false; -#endif + return is_blk (fs_mode); } bool file_stat::is_chr (void) const { -#ifdef S_ISCHR - return S_ISCHR (fs_mode); -#else - return false; -#endif + return is_chr (fs_mode); } bool file_stat::is_dir (void) const { -#ifdef S_ISDIR - return S_ISDIR (fs_mode); + return is_dir (fs_mode); +} + +bool +file_stat::is_fifo (void) const +{ + return is_fifo (fs_mode); +} + +bool +file_stat::is_lnk (void) const +{ + return is_lnk (fs_mode); +} + +bool +file_stat::is_reg (void) const +{ + return is_reg (fs_mode); +} + +bool +file_stat::is_sock (void) const +{ + return is_sock (fs_mode); +} + +bool +file_stat::is_blk (mode_t mode) +{ +#ifdef S_ISBLK + return S_ISBLK (mode); #else return false; #endif } bool -file_stat::is_fifo (void) const +file_stat::is_chr (mode_t mode) +{ +#ifdef S_ISCHR + return S_ISCHR (mode); +#else + return false; +#endif +} + +bool +file_stat::is_dir (mode_t mode) { -#ifdef S_ISFIFO - return S_ISFIFO (fs_mode); +#ifdef S_ISDIR + return S_ISDIR (mode); #else return false; #endif } bool -file_stat::is_lnk (void) const +file_stat::is_fifo (mode_t mode) { -#ifdef S_ISLNK - return S_ISLNK (fs_mode); +#ifdef S_ISFIFO + return S_ISFIFO (mode); #else return false; #endif } bool -file_stat::is_reg (void) const +file_stat::is_lnk (mode_t mode) { -#ifdef S_ISREG - return S_ISREG (fs_mode); +#ifdef S_ISLNK + return S_ISLNK (mode); #else return false; #endif } bool -file_stat::is_sock (void) const +file_stat::is_reg (mode_t mode) +{ +#ifdef S_ISREG + return S_ISREG (mode); +#else + return false; +#endif +} + +bool +file_stat::is_sock (mode_t mode) { #ifdef S_ISSOCK - return S_ISSOCK (fs_mode); + return S_ISSOCK (mode); #else return false; #endif diff --git a/liboctave/file-stat.h b/liboctave/file-stat.h --- a/liboctave/file-stat.h +++ b/liboctave/file-stat.h @@ -85,6 +85,14 @@ bool is_reg (void) const; bool is_sock (void) const; + static bool is_blk (mode_t mode); + static bool is_chr (mode_t mode); + static bool is_dir (mode_t mode); + static bool is_fifo (mode_t mode); + static bool is_lnk (mode_t mode); + static bool is_reg (mode_t mode); + static bool is_sock (mode_t mode); + ino_t ino (void) const { return fs_ino; } dev_t dev (void) const { return fs_dev; } @@ -111,6 +119,8 @@ long blocks (void) const { return fs_blocks; } #endif + mode_t mode (void) const { return fs_mode; } + std::string mode_as_string (void) const; bool ok (void) const { return initialized && ! fail; } diff --git a/scripts/ChangeLog b/scripts/ChangeLog --- a/scripts/ChangeLog +++ b/scripts/ChangeLog @@ -1,5 +1,7 @@ 2005-09-28 John W. Eaton + * miscellaneous/single.m: New function. + * statistics/base/unidrnd.m: New function. 2005-09-27 John W. Eaton diff --git a/scripts/miscellaneous/single.m b/scripts/miscellaneous/single.m new file mode 100644 --- /dev/null +++ b/scripts/miscellaneous/single.m @@ -0,0 +1,37 @@ +## Copyright (C) 2005 John W. Eaton +## +## This file is part of Octave. +## +## Octave is free software; you can redistribute it and/or modify it +## under the terms of the GNU General Public License as published by +## the Free Software Foundation; either version 2, or (at your option) +## any later version. +## +## Octave is distributed in the hope that it will be useful, but +## WITHOUT ANY WARRANTY; without even the implied warranty of +## MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU +## General Public License for more details. +## +## You should have received a copy of the GNU General Public License +## along with Octave; see the file COPYING. If not, write to the Free +## Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA +## 02110-1301, USA. + +## -*- texinfo -*- +## @deftypefn {Function File} {} single (@var{val}) +## Convert the numeric value @var{val} to single precision. +## +## @strong{Note}: this function currently returns its argument unchanged +## because Octave does not yet have a single-precision numeric data +## type. +## @end deftypefn + +function retval = single (val) + + if (nargin == 1 && isnumeric (val)) + retval = val; + else + usage ("single (val)"); + endif + +endfunction diff --git a/src/ChangeLog b/src/ChangeLog --- a/src/ChangeLog +++ b/src/ChangeLog @@ -1,3 +1,24 @@ +2005-09-29 John W. Eaton + + * syscalls.cc (mk_stat_map): Store mode too. + (FS_ISREG, FS_ISDIR, FS_ISCHR, FS_ISBLK, FS_ISFIFO, FS_ISLNK, + FS_ISSOCK): New functions. + (Fstat): Fix docstring. + +2005-09-28 John W. Eaton + + * oct-stream.cc (printf_value_cache::double_value): Force + character strings to be converted to ASCII equivalents. + + * data.cc (Fcomplex): New function. + + * ov-type-conv.h (OCTAVE_TYPE_CONV_BODY3): Return arg unchanged if + class name is same as name of conversion. + + * dirfns.cc (Frmdir, Fmkdir): For compatibility, return true for + success and false for failure. Return third value, msgid. + (Frmdir): Handle second arg for recursive behavior. + 2005-09-23 John W. Eaton * parse.y (load_fcn_from_file): Don't look in path if file is diff --git a/src/data.cc b/src/data.cc --- a/src/data.cc +++ b/src/data.cc @@ -38,6 +38,8 @@ #include "error.h" #include "gripes.h" #include "ov.h" +#include "ov-complex.h" +#include "ov-cx-mat.h" #include "variables.h" #include "oct-obj.h" #include "utils.h" @@ -1149,6 +1151,127 @@ return retval; } +// XXX FIXME XXX -- perhaps this should be implemented with an +// octave_value member function? + +DEFUN (complex, args, , + "-*- texinfo -*-\n\ +@deftypefn {Built-in Function} {} complex (@var{val})\n\ +@deftypefnx {Built-in Function} {} complex (@var{re}, @var{im})\n\ +Convert @var{x} to a complex value.\n\ +@end deftypefn") +{ + octave_value retval; + + int nargin = args.length (); + + if (nargin == 1) + { + octave_value arg = args(0); + + if (arg.is_complex_type ()) + retval = arg; + else + { + if (arg.numel () == 1) + { + Complex val = arg.complex_value (); + + if (! error_state) + retval = octave_value (new octave_complex (val)); + } + else + { + ComplexNDArray val = arg.complex_array_value (); + + if (! error_state) + retval = octave_value (new octave_complex_matrix (val)); + } + + if (error_state) + error ("complex: invalid conversion"); + } + } + else if (nargin == 2) + { + octave_value re = args(0); + octave_value im = args(1); + + if (re.numel () == 1) + { + double re_val = re.double_value (); + + if (im.numel () == 1) + { + double im_val = im.double_value (); + + if (! error_state) + retval = octave_value (new octave_complex (Complex (re_val, im_val))); + } + else + { + const NDArray im_val = im.array_value (); + + if (! error_state) + { + ComplexNDArray result (im_val.dims (), Complex ()); + + for (octave_idx_type i = 0; i < im_val.numel (); i++) + result.xelem (i) = Complex (re_val, im_val(i)); + + retval = octave_value (new octave_complex_matrix (result)); + } + } + } + else + { + const NDArray re_val = re.array_value (); + + if (im.numel () == 1) + { + double im_val = im.double_value (); + + if (! error_state) + { + ComplexNDArray result (re_val.dims (), Complex ()); + + for (octave_idx_type i = 0; i < re_val.numel (); i++) + result.xelem (i) = Complex (re_val(i), im_val); + + retval = octave_value (new octave_complex_matrix (result)); + } + } + else + { + const NDArray im_val = im.array_value (); + + if (! error_state) + { + if (re_val.dims () == im_val.dims ()) + { + ComplexNDArray result (re_val.dims (), Complex ()); + + for (octave_idx_type i = 0; i < re_val.numel (); i++) + result.xelem (i) = Complex (re_val(i), im_val(i)); + + retval = octave_value (new octave_complex_matrix (result)); + } + else + error ("complex: dimension mismatch"); + } + } + } + + if (error_state) + error ("complex: invalid conversion"); + } + else + print_usage ("complex"); + + return retval; +} + + DEFUN (isreal, args, , "-*- texinfo -*-\n\ @deftypefn {Built-in Function} {} isreal (@var{x})\n\ diff --git a/src/dirfns.cc b/src/dirfns.cc --- a/src/dirfns.cc +++ b/src/dirfns.cc @@ -284,23 +284,25 @@ return retval; } -// XXX FIXME XXX -- should probably also allow second arg to specify -// mode. +// XXX FIXME XXX -- should maybe also allow second arg to specify +// mode? OTOH, that might cause trouble with compatibility later... DEFUN (mkdir, args, , "-*- texinfo -*-\n\ -@deftypefn {Built-in Function} {[@var{err}, @var{msg}] =} mkdir (@var{dir})\n\ +@deftypefn {Built-in Function} {[@var{status}, @var{msg}, @var{msgid}] =} mkdir (@var{dir})\n\ Create a directory named @var{dir}.\n\ \n\ -If successful, @var{err} is 0 and @var{msg} is an empty string.\n\ -Otherwise, @var{err} is nonzero and @var{msg} contains a\n\ -system-dependent error message.\n\ +If successful, @var{status} is 1, with @var{msg} and @var{msgid} empty\n\ +character strings. Otherwise, @var{status} is 0, @var{msg} contains a\n\ +system-dependent error message, and @var{msgid} contains a unique\n\ +message identifier.\n\ @end deftypefn") { octave_value_list retval; + retval(2) = std::string (); retval(1) = std::string (); - retval(0) = -1.0; + retval(0) = false; if (args.length () == 1) { @@ -315,10 +317,13 @@ int status = file_ops::mkdir (file_ops::tilde_expand (dirname), 0777, msg); - retval(0) = status; - if (status < 0) - retval(1) = msg; + { + retval(2) = "mkdir"; + retval(1) = msg; + } + else + retval(0) = true; } } else @@ -329,20 +334,28 @@ DEFUN (rmdir, args, , "-*- texinfo -*-\n\ -@deftypefn {Built-in Function} {[@var{err}, @var{msg}] =} rmdir (@var{dir})\n\ +@deftypefn {Built-in Function} {[@var{status}, @var{msg}, @var{msgid}] =} rmdir (@var{dir})\n\ +@deftypefnx {Built-in Function} {[@var{status}, @var{msg}, @var{msgid}] =} rmdir (@var{dir}, @code{\"s\"})\n\ Remove the directory named @var{dir}.\n\ \n\ -If successful, @var{err} is 0 and @var{msg} is an empty string.\n\ -Otherwise, @var{err} is nonzero and @var{msg} contains a\n\ -system-dependent error message.\n\ +If successful, @var{status} is 1, with @var{msg} and @var{msgid} empty\n\ +character strings. Otherwise, @var{status} is 0, @var{msg} contains a\n\ +system-dependent error message, and @var{msgid} contains a unique\n\ +message identifier.\n\ +\n\ +If the optional second parameter is suplied, recursively remove all\n\ +subdirectories as well.\n\ @end deftypefn") { octave_value_list retval; + retval(2) = std::string (); retval(1) = std::string (); - retval(0) = -1.0; + retval(0) = false; - if (args.length () == 1) + int nargin = args.length (); + + if (nargin == 1 || nargin == 2) { std::string dirname = args(0).string_value (); @@ -352,12 +365,19 @@ { std::string msg; - int status = file_ops::rmdir (file_ops::tilde_expand (dirname), msg); + std::string fulldir = file_ops::tilde_expand (dirname); - retval(0) = status; + int status = (nargin == 1) + ? file_ops::rmdir (fulldir, msg) + : file_ops::recursive_rmdir (fulldir, msg); if (status < 0) - retval(1) = msg; + { + retval(2) = "rmdir"; + retval(1) = msg; + } + else + retval(0) = true; } } else diff --git a/src/oct-stream.cc b/src/oct-stream.cc --- a/src/oct-stream.cc +++ b/src/oct-stream.cc @@ -2323,7 +2323,9 @@ { octave_value tmp_val = values (val_idx); - curr_val = tmp_val.array_value (); + // Force string conversion here for compatibility. + + curr_val = tmp_val.array_value (true); if (! error_state) { diff --git a/src/ov-type-conv.h b/src/ov-type-conv.h --- a/src/ov-type-conv.h +++ b/src/ov-type-conv.h @@ -35,7 +35,11 @@ \ int t_result = MATRIX_RESULT_T::static_type_id (); \ \ - if (t_arg != t_result) \ + if (t_arg == t_result || arg.class_name () == #NAME) \ + { \ + retval = arg; \ + } \ + else \ { \ type_conv_fcn cf \ = octave_value_typeinfo::lookup_type_conv_op (t_arg, t_result); \ @@ -62,8 +66,6 @@ gripe_invalid_conversion (arg_tname, result_tname); \ } \ } \ - else \ - retval = arg; \ } \ else \ print_usage (#NAME); \ diff --git a/src/syscalls.cc b/src/syscalls.cc --- a/src/syscalls.cc +++ b/src/syscalls.cc @@ -67,6 +67,7 @@ m.assign ("dev", static_cast (fs.dev ())); m.assign ("ino", fs.ino ()); + m.assign ("mode", fs.mode ()); m.assign ("modestr", fs.mode_as_string ()); m.assign ("nlink", fs.nlink ()); m.assign ("uid", fs.uid ()); @@ -711,6 +712,12 @@ @item ino\n\ File number of the file.\n\ \n\ +@item mode\n\ +File mode, as an integer. Use the functions @code{S_ISREG},\n\ +@code{S_ISDIR}, @code{S_ISCHR}, @code{S_ISBLK}, @code{S_ISFIFO},\n\ +@code{S_ISLNK}, or @code{S_ISSOCK} to extract information from this\n\ +value.\n\ +\n\ @item modestr\n\ File mode, as a string of ten letters or dashes as would be returned by\n\ @kbd{ls -l}.\n\ @@ -775,6 +782,7 @@ gid = 6\n\ nlink = 1\n\ blocks = 768\n\ + mode = -rw-r--r--\n\ modestr = -rw-r--r--\n\ ino = 9316\n\ dev = 2049\n\ @@ -815,6 +823,179 @@ return retval; } +DEFUNX ("S_ISREG", FS_ISREG, args, , + "-*- texinfo -*-\n\ +@deftypefn {Built-in Function} {} S_ISREG (@var{mode})\n\ +Return true if @var{mode} corresponds to a regular file. The value\n\ +of @var{mode} is assumed to be returned from a call to @code{stat}.\n\ +@seealso{stat, lstat}\n\ +@end deftypefn") +{ + octave_value retval = false; + + if (args.length () == 1) + { + double mode = args(0).double_value (); + + if (! error_state) + retval = file_stat::is_reg (static_cast (mode)); + else + error ("S_ISREG: invalid mode value"); + } + else + print_usage ("S_ISREG"); + + return retval; +} + +DEFUNX ("S_ISDIR", FS_ISDIR, args, , + "-*- texinfo -*-\n\ +@deftypefn {Built-in Function} {} S_ISDIR (@var{mode})\n\ +Return true if @var{mode} corresponds to a directory. The value\n\ +of @var{mode} is assumed to be returned from a call to @code{stat}.\n\ +@seealso{stat, lstat}\n\ +@end deftypefn") +{ + octave_value retval = false; + + if (args.length () == 1) + { + double mode = args(0).double_value (); + + if (! error_state) + retval = file_stat::is_dir (static_cast (mode)); + else + error ("S_ISDIR: invalid mode value"); + } + else + print_usage ("S_ISDIR"); + + return retval; +} + +DEFUNX ("S_ISCHR", FS_ISCHR, args, , + "-*- texinfo -*-\n\ +@deftypefn {Built-in Function} {} S_ISCHR (@var{mode})\n\ +Return true if @var{mode} corresponds to a character devicey. The value\n\ +of @var{mode} is assumed to be returned from a call to @code{stat}.\n\ +@seealso{stat, lstat}\n\ +@end deftypefn") +{ + octave_value retval = false; + + if (args.length () == 1) + { + double mode = args(0).double_value (); + + if (! error_state) + retval = file_stat::is_chr (static_cast (mode)); + else + error ("S_ISCHR: invalid mode value"); + } + else + print_usage ("S_ISCHR"); + + return retval; +} + +DEFUNX ("S_ISBLK", FS_ISBLK, args, , + "-*- texinfo -*-\n\ +@deftypefn {Built-in Function} {} S_ISBLK (@var{mode})\n\ +Return true if @var{mode} corresponds to a block device. The value\n\ +of @var{mode} is assumed to be returned from a call to @code{stat}.\n\ +@seealso{stat, lstat}\n\ +@end deftypefn") +{ + octave_value retval = false; + + if (args.length () == 1) + { + double mode = args(0).double_value (); + + if (! error_state) + retval = file_stat::is_blk (static_cast (mode)); + else + error ("S_ISBLK: invalid mode value"); + } + else + print_usage ("S_ISBLK"); + + return retval; +} + +DEFUNX ("S_ISFIFO", FS_ISFIFO, args, , + "-*- texinfo -*-\n\ +@deftypefn {Built-in Function} {} S_ISFIFO (@var{mode})\n\ +Return true if @var{mode} corresponds to a fifo. The value\n\ +of @var{mode} is assumed to be returned from a call to @code{stat}.\n\ +@seealso{stat, lstat}\n\ +@end deftypefn") +{ + octave_value retval = false; + + if (args.length () == 1) + { + double mode = args(0).double_value (); + + if (! error_state) + retval = file_stat::is_fifo (static_cast (mode)); + else + error ("S_ISFIFO: invalid mode value"); + } + else + print_usage ("S_ISFIFO"); + + return retval; +} + +DEFUNX ("S_ISLNK", FS_ISLNK, args, , + "-*- texinfo -*-\n\ +@deftypefn {Built-in Function} {} S_ISLNK (@var{mode})\n\ +Return true if @var{mode} corresponds to a symbolic link. The value\n\ +of @var{mode} is assumed to be returned from a call to @code{stat}.\n\ +@seealso{stat, lstat}\n\ +@end deftypefn") +{ + octave_value retval = false; + + if (args.length () == 1) + { + double mode = args(0).double_value (); + + if (! error_state) + retval = file_stat::is_lnk (static_cast (mode)); + else + error ("S_ISLNK: invalid mode value"); + } + else + print_usage ("S_ISLNK"); + + return retval; +} + +DEFUNX ("S_ISSOCK", FS_ISSOCK, args, , + "-*- texinfo -*-\n\ +@deftypefn {Built-in Function} {} S_ISSOCK (@var{mode})\n\ +@seealso{stat, lstat}\n\ +@end deftypefn") +{ + octave_value retval = false; + + if (args.length () == 1) + { + double mode = args(0).double_value (); + + if (! error_state) + retval = file_stat::is_sock (static_cast (mode)); + else + error ("S_ISSOCK: invalid mode value"); + } + else + print_usage ("S_ISSOCK"); + + return retval; +} + DEFUN (unlink, args, , "-*- texinfo -*-\n\ @deftypefn {Built-in Function} {[@var{err}, @var{msg}] =} unlink (@var{file})\n\ diff --git a/test/octave.test/string/split-4.m b/test/octave.test/string/split-4.m new file mode 100644 --- /dev/null +++ b/test/octave.test/string/split-4.m @@ -0,0 +1,1 @@ +split ("foo", "bar", 3, 4)