# HG changeset patch # User jwe # Date 797476474 0 # Node ID 92609e161b29d514b9615976a1871cd0c8675810 # Parent 7d7c3eaa1d3b46de900685df8bdbd365da26ef1b [project @ 1995-04-10 01:08:57 by jwe] diff -r 7d7c3eaa1d3b -r 92609e161b29 liboctave/Array.h --- a/liboctave/Array.h Mon Apr 10 01:04:46 1995 +0000 +++ b/liboctave/Array.h Mon Apr 10 01:14:34 1995 +0000 @@ -148,6 +148,8 @@ Array2 (const Array2& a); Array2 (const DiagArray& a); + ~Array2 (void) { } + Array2& operator = (const Array2& a); int dim1 (void) const; @@ -192,6 +194,8 @@ Array3 (int n, int m, int k, const T& val); Array3 (const Array3& a); + ~Array3 (void) { } + Array3& operator = (const Array3& a); int dim3 (void) const; @@ -303,6 +307,8 @@ DiagArray (const Array& a); DiagArray (const DiagArray& a); + ~DiagArray (void) { } + DiagArray& operator = (const DiagArray& a); int dim1 (void) const; diff -r 7d7c3eaa1d3b -r 92609e161b29 liboctave/MArray.cc --- a/liboctave/MArray.cc Mon Apr 10 01:04:46 1995 +0000 +++ b/liboctave/MArray.cc Mon Apr 10 01:14:34 1995 +0000 @@ -77,10 +77,10 @@ } #define DO_VS_OP2(OP) \ - int l = length (); \ + int l = a.length (); \ if (l > 0) \ { \ - T *tmp = fortran_vec (); \ + T *tmp = a.fortran_vec (); \ for (int i = 0; i < l; i++) \ tmp[i] OP s; \ } @@ -88,10 +88,10 @@ #define DO_VV_OP2(OP) \ do \ { \ - T *tmp = fortran_vec (); \ - const T *rhs = a.data (); \ + T *a_tmp = a.fortran_vec (); \ + const T *b_tmp = b.data (); \ for (int i = 0; i < l; i++) \ - tmp[i] += rhs[i]; \ + a_tmp[i] += b_tmp[i]; \ } \ while (0) @@ -103,52 +103,52 @@ template MArray& -MArray::operator += (const T& s) +operator += (MArray& a, const T& s) { DO_VS_OP2 (+=) - return *this; + return a; } template MArray& -MArray::operator -= (const T& s) +operator -= (MArray& a, const T& s) { DO_VS_OP2 (-=) - return *this; + return a; } // Element by element MArray by MArray ops. template MArray& -MArray::operator += (const MArray& a) +operator += (MArray& a, const MArray& b) { - int l = length (); + int l = a.length (); if (l > 0) { - if (l != a.length ()) + if (l != b.length ()) (*current_liboctave_error_handler) \ ("nonconformant += array operation attempted"); \ else DO_VV_OP2 (+=); } - return *this; + return a; } template MArray& -MArray::operator -= (const MArray& a) +operator -= (MArray& a, const MArray& b) { - int l = length (); + int l = a.length (); if (l > 0) { - if (l != a.length ()) + if (l != b.length ()) (*current_liboctave_error_handler) \ ("nonconformant -= array operation attempted"); \ else DO_VV_OP2 (-=); } - return *this; + return a; } // Element by element MArray by scalar ops. @@ -234,29 +234,29 @@ template MArray2& -MArray2::operator += (const T& s) +operator += (MArray2& a, const T& s) { DO_VS_OP2 (+=) - return *this; + return a; } template MArray2& -MArray2::operator -= (const T& s) +operator -= (MArray2& a, const T& s) { DO_VS_OP2 (-=) - return *this; + return a; } // Element by element MArray2 by MArray2 ops. template MArray2& -MArray2::operator += (const MArray2& a) +operator += (MArray2& a, const MArray2& b) { - int r = rows (); - int c = cols (); - if (r != a.rows () || c != a.cols ()) + int r = a.rows (); + int c = a.cols (); + if (r != b.rows () || c != b.cols ()) { (*current_liboctave_error_handler) ("nonconformant += array operation attempted"); @@ -269,16 +269,16 @@ DO_VV_OP2 (+=); } } - return *this; + return a; } template MArray2& -MArray2::operator -= (const MArray2& a) +operator -= (MArray2& a, const MArray2& b) { - int r = rows (); - int c = cols (); - if (r != a.rows () || c != a.cols ()) + int r = a.rows (); + int c = a.cols (); + if (r != b.rows () || c != b.cols ()) { (*current_liboctave_error_handler) ("nonconformant -= array operation attempted"); @@ -291,7 +291,7 @@ DO_VV_OP2 (-=); } } - return *this; + return a; } // Element by element MArray2 by scalar ops. @@ -371,18 +371,48 @@ template MDiagArray& -MDiagArray::operator += (const MDiagArray& a) +operator += (MDiagArray& a, const MDiagArray& b) { - // XXX FIXME XXX - return *this; + int r = a.rows (); + int c = a.cols (); + if (r != b.rows () || c != b.cols ()) + { + (*current_liboctave_error_handler) + ("nonconformant array " OP_STR " attempted"); + return MArray2 (); + } + else + { + int l = a.length (); + T *a_tmp = a.fortran_vec (); + const T *b_tmp = b.data (); + for (int i = 0; i < l; i++) + a_tmp[i] += b_tmp[i]; + } + return a; } template MDiagArray& -MDiagArray::operator -= (const MDiagArray& a) +operator -= (MDiagArray& a, const MDiagArray& b) { - // XXX FIXME XXX - return *this; + int r = a.rows (); + int c = a.cols (); + if (r != b.rows () || c != b.cols ()) + { + (*current_liboctave_error_handler) + ("nonconformant array " OP_STR " attempted"); + return MArray2 (); + } + else + { + int l = a.length (); + T *a_tmp = a.fortran_vec (); + const T *b_tmp = b.data (); + for (int i = 0; i < l; i++) + a_tmp[i] -= b_tmp[i]; + } + return a; } // Element by element MDiagArray by scalar ops. diff -r 7d7c3eaa1d3b -r 92609e161b29 liboctave/MArray.h --- a/liboctave/MArray.h Mon Apr 10 01:04:46 1995 +0000 +++ b/liboctave/MArray.h Mon Apr 10 01:14:34 1995 +0000 @@ -53,6 +53,8 @@ MArray (const Array& a) : Array (a) { } MArray (const MArray& a) : Array (a) { } + ~MArray (void) { } + MArray& operator = (const MArray& a) { Array::operator = (a); @@ -61,13 +63,13 @@ // Element by element MArray by scalar ops. - MArray& operator += (const T& s); - MArray& operator -= (const T& s); + friend MArray& operator += (MArray& a, const T& s); + friend MArray& operator -= (MArray& a, const T& s); // Element by element MArray by MArray ops. - MArray& operator += (const MArray& a); - MArray& operator -= (const MArray& a); + friend MArray& operator += (MArray& a, const MArray& b); + friend MArray& operator -= (MArray& a, const MArray& b); // Element by element MArray by scalar ops. @@ -115,6 +117,8 @@ MArray2 (const MArray2& a) : Array2 (a) { } MArray2 (const MDiagArray& a); + ~MArray2 (void) { } + MArray2& operator = (const MArray2& a) { Array2::operator = (a); @@ -123,13 +127,13 @@ // Element by element MArray2 by scalar ops. - MArray2& operator += (const T& s); - MArray2& operator -= (const T& s); + friend MArray2& operator += (MArray2& a, const T& s); + friend MArray2& operator -= (MArray2& a, const T& s); // Element by element MArray2 by MArray2 ops. - MArray2& operator += (const MArray2& a); - MArray2& operator -= (const MArray2& a); + friend MArray2& operator += (MArray2& a, const MArray2& b); + friend MArray2& operator -= (MArray2& a, const MArray2& b); // Element by element MArray2 by scalar ops. @@ -178,6 +182,8 @@ MDiagArray (const MDiagArray& a) : DiagArray (a) { } MDiagArray (const MArray& a) : DiagArray (a) { } + ~MDiagArray (void) { } + MDiagArray& operator = (const MDiagArray& a) { DiagArray::operator = (a); @@ -186,8 +192,8 @@ // Element by element MDiagArray by MDiagArray ops. - MDiagArray& operator += (const MDiagArray& a); - MDiagArray& operator -= (const MDiagArray& a); + friend MDiagArray& operator += (MDiagArray& a, const MDiagArray& b); + friend MDiagArray& operator -= (MDiagArray& a, const MDiagArray& b); // Element by element MDiagArray by scalar ops. diff -r 7d7c3eaa1d3b -r 92609e161b29 src/file-io.cc --- a/src/file-io.cc Mon Apr 10 01:04:46 1995 +0000 +++ b/src/file-io.cc Mon Apr 10 01:14:34 1995 +0000 @@ -22,20 +22,30 @@ */ // Written by John C. Campbell . +// +// Thomas Baier added the following functions: +// +// popen pclose execute sync_system async_system +// waitpid mkfifo unlink + #ifdef HAVE_CONFIG_H -#include "config.h" +#include #endif -#include +#include #include #include #include #include #include #include +#include +#include #include +#include + #include "dMatrix.h" #include "statdefs.h" @@ -285,7 +295,7 @@ } DEFUN ("fclose", Ffclose, Sfclose, 1, 1, - "fclose (FILENAME or FILENUM): close a file") + "fclose (FILENAME or FILENUM): close a file") { Octave_object retval; @@ -1693,8 +1703,8 @@ SIZE : size specification for the Data matrix\n\ PRECISION : type of data to read, valid types are\n\ \n\ - 'char', 'schar', 'short', 'int', 'long', 'float'\n\ - 'double', 'uchar', 'ushort', 'uint', 'ulong'\n\ + \"char\" \"schar\" \"short\" \"int\" \"long\" \"float\"\n\ + \"double\" \"uchar\" \"ushort\" \"uint\" \"ulong\"\n\ \n\ DATA : matrix in which the data is stored\n\ COUNT : number of elements read") @@ -1774,8 +1784,8 @@ DATA : matrix of elements to be written\n\ PRECISION : type of data to read, valid types are\n\ \n\ - 'char', 'schar', 'short', 'int', 'long', 'float'\n\ - 'double', 'uchar', 'ushort', 'uint', 'ulong'\n\ + \"char\" \"schar\" \"short\" \"int\" \"long\" \"float\"\n\ + \"double\" \"uchar\" \"ushort\" \"uint\" \"ulong\"\n\ \n\ COUNT : number of elements written") { @@ -1883,6 +1893,495 @@ return retval; } +static Octave_object +popen_internal (const Octave_object& args) +{ + Octave_object retval; + + if (! args(0).is_string ()) + { + error ("popen: file name must be a string"); + return retval; + } + + char *name = args(0).string_value (); + + Pix p = return_valid_file (name); + + if (p) + { + file_info file = file_list (p); + + retval(0) = (double) file.number (); + + return retval; + } + + if (! args(1).is_string ()) + { + error ("popen: file mode must be a string"); + return retval; + } + + char *mode = args(1).string_value (); + + if (mode[1] || (mode[0] != 'w' && mode[0] != 'r')) + { + error ("popen: invalid mode, must be either \"r\" or \"w\"."); + return retval; + } + + struct stat buffer; + if (stat (name, &buffer) == 0 && (buffer.st_mode & S_IFDIR) == S_IFDIR) + { + error ("popen: can't open directory"); + return retval; + } + + FILE *file_ptr = popen (name, mode); + + if (! file_ptr) + { + error ("popen: unable to start process `%s'", name); + return retval; + } + + int number = file_list.length () + 1; + + file_info file (number, name, file_ptr, mode); + file_list.append (file); + + retval(0) = (double) number; + + return retval; +} + +DEFUN ("popen", Fpopen, Spopen, 2, 1, + "FILENUM = popen (FILENAME, MODE)\n\ +\n\ + start a process and create a pipe. Valid values for mode are:\n\ +\n\ + \"r\" : connect stdout of process to pipe\n\ + \"w\" : connect stdin of process to pipe") +{ + Octave_object retval; + + int nargin = args.length (); + + if (nargin != 2) + print_usage ("popen"); + else + retval = popen_internal (args); + + return retval; +} + +static Octave_object +pclose_internal (const Octave_object& args) +{ + Octave_object retval; + + Pix p = return_valid_file (args(0)); + + if (! p) + return retval; + + file_info file = file_list (p); + + if (file.number () < 3) + { + warning ("pclose: can't close stdin, stdout, or stderr!"); + return retval; + } + + int success = pclose (file.fptr ()); + file_list.del (p); + + if (success == 0) + retval(0) = 1.0; // succeeded + else + { + error ("pclose: error on closing file"); + retval(0) = 0.0; // failed + } + + return retval; +} + +DEFUN ("pclose", Fpclose, Spclose, 1, 1, + "pclose (FILENAME or FILENUM)\n\ +\n\ + Close a pipe and terminate the associated process") +{ + Octave_object retval; + + int nargin = args.length (); + + if (nargin != 1) + print_usage ("pclose"); + else + retval = pclose_internal (args); + + return retval; +} + +static Octave_object +execute_internal (const Octave_object& args, int nargout) +{ + Octave_object retval (3, tree_constant (-1.0)); + + pid_t pid = 0; + int stdin_pipe[2]; + int stdout_pipe[2]; + FILE *stdin_file; + FILE *stdout_file; + int new_stdin; + int new_stdout; + + if (! args(0).is_string ()) + { + error ("execute: file name must be a string"); + return retval; + } + + char *name = args(0).string_value (); + + if (pipe (stdin_pipe) || pipe (stdout_pipe)) + { + error ("execute: pipe creation failed"); + return retval; + } + + pid = fork (); + + if (pid < (pid_t) 0) + { + error ("execute: fork failed - can't create child process"); + return retval; + } + + if (pid == (pid_t) 0) + { + close (stdin_pipe[1]); + close (stdout_pipe[0]); + + dup2 (stdin_pipe[0], STDIN_FILENO); + close (stdin_pipe[0]); + + dup2 (stdout_pipe[1], STDOUT_FILENO); + close (stdout_pipe[1]); + + if (execlp (name, name, 0) == -1) + error ("execute: unable to start process `%s'", name); + + exit (0); + return 0.0; + } + else + { + close (stdin_pipe[0]); + close (stdout_pipe[1]); + + stdout_file = fdopen (stdout_pipe[0], "r"); + stdin_file = fdopen (stdin_pipe[1], "w"); + + if (fcntl (fileno (stdout_file), F_SETFL, O_NONBLOCK) < 0) + { + error ("execute: error setting file mode"); + return retval; + } + + new_stdin = file_list.length () + 1; + new_stdout = new_stdin + 1; + + file_info new_stdin_file_ptr (new_stdin, name, stdin_file, "w"); + file_info new_stdout_file_ptr (new_stdout, name, stdout_file, "r"); + + file_list.append (new_stdin_file_ptr); + file_list.append (new_stdout_file_ptr); + } + + retval(2) = (double) pid; + retval(1) = (double) new_stdout; + retval(0) = (double) new_stdin; + + return retval; +} + +DEFUN ("execute", Fexecute, Sexecute, 1, 3, + "[STDIN, STDOUT, PID] = execute (COMMAND)\n\ +\n\ + Start a program and redirect its stdin to STDIN and its stdout to STDOUT") +{ + Octave_object retval; + + int nargin = args.length (); + + if (nargin != 1) + print_usage ("execute"); + else + retval = execute_internal (args, nargout); + + return retval; +} + +static Octave_object +sync_system_internal (const Octave_object& args) +{ + Octave_object retval (1, tree_constant (-1.0)); + + if (! args(0).is_string ()) + { + error ("sync_system: file name must be a string"); + return retval; + } + + char *name = args(0).string_value (); + + retval (0) = (double) system (name); + return retval; +} + +DEFUN ("sync_system", Fsync_system, Ssync_system, 1, 1, + "RETCODE = sync_system (FILENAME)\n\ +\n\ + Start a program and wait until it terminates") +{ + Octave_object retval; + + int nargin = args.length (); + + if (nargin != 1) + print_usage ("sync_system"); + else + retval = sync_system_internal (args); + + return retval; +} + +static Octave_object +async_system_internal (const Octave_object& args) +{ + Octave_object retval (1, tree_constant (-1.0)); + pid_t pid; + + if (! args(0).is_string ()) + { + error ("async_system: file name must be a string"); + return retval; + } + + char *name = args(0).string_value (); + + pid = fork (); + + if (pid < 0) + { + error ("async_system: fork failed -- can't create child process"); + return retval; + } + + if (pid == 0) + { + system (name); + exit (0); + retval (0) = 0.0; + return retval; + } + else + { + retval (0) = (double) pid; + return retval; + } +} + +DEFUN ("async_system", Fasync_system, Sasync_system, 1, 1, + "PID = async_system (FILENAME)\n\ +\n\ + Create a new process and start FILENAME") +{ + Octave_object retval; + + int nargin = args.length (); + + if (nargin != 1) + print_usage ("async_system"); + else + retval = async_system_internal (args); + + return retval; +} + +static Octave_object +waitpid_internal (const Octave_object& args) +{ + Octave_object retval (1, tree_constant (-1.0)); + + double pid_num = args(0).double_value (); + + if (! error_state) + { + if (D_NINT (pid_num) != pid_num) + error ("waitpid: PID must be an integer value"); + else + { + pid_t pid = (pid_t) pid_num; + + int options = 0; + + if (args.length () == 2) + { + double options_num = args(1).double_value (); + + if (! error_state) + { + if (D_NINT (options_num) != options_num) + error ("waitpid: PID must be an integer value"); + else + { + options = NINT (options_num); + if (options < 0 || options > 3) + error ("waitpid: invalid OPTIONS value specified"); + } + } + } + + if (! error_state) + retval (0) = (double) waitpid (pid, 0, options); + } + } + + return retval; +} + +DEFUN ("waitpid", Fwaitpid, Swaitpid, 1, 1, + "STATUS = waitpid (PID, OPTIONS)\n\ +\n\ + wait for process PID to terminate\n\ +\n\ + PID can be:\n\ +\n\ + -1 : wait for any child process\n\ + 0 : wait for any child process whose process group ID is equal to\n\ + that of the Octave interpreter process.\n\ + > 0 : wait for termination of the child process with ID PID.\n\ +\n\ + OPTIONS is:\n\ +\n\ + 0 : wait until signal is received or a child process exits (this\n\ + is the default if the OPTIONS argument is missing) \n\ + 1 : do not hang if status is not immediately available\n\ + 2 : report the status of any child processes that are\n\ + stopped, and whose status has not yet been reported\n\ + since they stopped\n\ + 3 : implies both 1 and 2\n\ +\n\ + STATUS is:\n\ +\n\ + -1 : if an error occured\n\ + > 0 : the process ID of the child process that exited") +{ + Octave_object retval; + + int nargin = args.length (); + + if (nargin == 1 || nargin == 2) + retval = waitpid_internal (args); + else + print_usage ("waitpid"); + + return retval; +} + +static Octave_object +mkfifo_internal (const Octave_object& args) +{ + Octave_object retval (1, tree_constant (-1.0)); + + if (! args(0).is_string ()) + { + error ("mkfifo: file name must be a string"); + return retval; + } + + char *name = args(0).string_value (); + + if (! args(1).is_scalar_type ()) + { + error ("mkfifo: MODE must be an integer"); + return retval; + } + + long mode = (long) args(1).double_value (); + + retval (0) = (double) mkfifo (name, mode); + + return retval; +} + +DEFUN ("mkfifo", Fmkfifo, Smkfifo, 2, 1, + "STATUS = mkfifo (NAME, MODE)\n\ +\n\ + Create a FIFO special file named NAME with file mode MODE\n\ +\n\ + STATUS is:\n\ +\n\ + != 0 : if mkfifo failed\n\ + 0 : if the FIFO special file could be created") +{ + Octave_object retval; + + int nargin = args.length (); + + if (nargin != 2) + print_usage ("mkfifo"); + else + retval = mkfifo_internal (args); + + return retval; +} + +static Octave_object +unlink_internal (const Octave_object& args) +{ + Octave_object retval; + + if (! args(0).is_string ()) + { + error ("unlink: file name must be a string"); + retval (0) = -1.0; + return retval; + } + + char *name = args(0).string_value (); + + retval (0) = (double) unlink (name); + + return retval; +} + +DEFUN ("unlink", Funlink, Sunlink, 1, 1, + "STATUS = unlink (NAME)\n\ +\n\ + Delete the file NAME\n\ +\n\ + STATUS is:\n\ +\n\ + != 0 : if unlink failed\n\ + 0 : if the file could be successfully deleted") +{ + Octave_object retval; + + int nargin = args.length (); + + if (nargin != 1) + print_usage ("unlink"); + else + retval = unlink_internal (args); + + return retval; +} + /* ;;; Local Variables: *** ;;; mode: C++ *** diff -r 7d7c3eaa1d3b -r 92609e161b29 src/sighandlers.cc --- a/src/sighandlers.cc Mon Apr 10 01:04:46 1995 +0000 +++ b/src/sighandlers.cc Mon Apr 10 01:14:34 1995 +0000 @@ -22,15 +22,17 @@ */ #ifdef HAVE_CONFIG_H -#include "config.h" +#include #endif #include #ifdef HAVE_UNISTD_H #include #endif +#include #include #include +#include #include "sighandlers.h" #include "octave.h" @@ -72,6 +74,47 @@ #endif } +// Handle SIGCHLD. Should use waitpid and ignore stopped jobs. +// Needs to restore state of plotter such that it will be restarted +// again when needed. Needs to close file descriptors corresponding +// to processes started with execute(). + +#if 0 +static RETSIGTYPE +sigchld_handler (int i) +{ + int status; + pid_t pid = wait (&status); + + if (pid < 0) + cerr << "wait error\n"; + else + { + cerr << "sigchld caught, PID = " << pid << "; status: "; + + int lo_byte = (status & 0xff); + int hi_byte = ((status >> 8) & 0xff); + if (lo_byte == 0177) + { + cerr << "stopped with signal = " << hi_byte << "\n"; + } + else if (lo_byte) + { + int sig_num = (lo_byte & 0x7f); + cerr << "stopped with signal = " << sig_num << "\n"; + if (lo_byte & 0200) + cerr << "child dumped core\n"; + } + else + { + cerr << "exited with status = " << hi_byte << "\n"; + } + } + + signal (SIGCHLD, sigchld_handler); +} +#endif + // Handle SIGINT by restarting the parser (see octave.cc). // XXX FIXME XXX -- it would probably be good to try to use POSIX @@ -139,6 +182,12 @@ signal (SIGBUS, generic_sig_handler); #endif +#if 0 +#ifdef SIGCHLD + signal (SIGCHLD, sigchld_handler); +#endif +#endif + #ifdef SIGEMT signal (SIGEMT, generic_sig_handler); #endif