# HG changeset patch # User jwe # Date 830682007 0 # Node ID 36903d507b0e6e418ef858eb02f20750a25777bb # Parent a23645b0364e0d78431a708251d9ddb86d1e7c39 [project @ 1996-04-28 09:00:07 by jwe] diff --git a/src/dassl.cc b/src/dassl.cc --- a/src/dassl.cc +++ b/src/dassl.cc @@ -26,7 +26,7 @@ #include -#include +#include #include "DASSL.h" @@ -242,36 +242,33 @@ }; static void -print_dassl_option_list (void) +print_dassl_option_list (ostream& os) { - ostrstream output_buf; - print_usage ("dassl_options", 1); - output_buf << "\n" - << "Options for dassl include:\n\n" - << " keyword value\n" - << " ------- -----\n\n"; + os << "\n" + << "Options for dassl include:\n\n" + << " keyword value\n" + << " ------- -----\n\n"; DASSL_OPTIONS *list = dassl_option_table; const char *keyword; while ((keyword = list->keyword) != 0) { - output_buf.form (" %-40s ", keyword); + os.form (" %-40s ", keyword); double val = (dassl_opts.*list->d_get_fcn) (); if (val < 0.0) - output_buf << "computed automatically"; + os << "computed automatically"; else - output_buf << val; + os << val; - output_buf << "\n"; + os << "\n"; list++; } - output_buf << "\n" << ends; - maybe_page_output (output_buf); + os << "\n"; } static void @@ -328,7 +325,7 @@ if (nargin == 0) { - print_dassl_option_list (); + print_dassl_option_list (octave_stdout); return retval; } else if (nargin == 1 || nargin == 2) diff --git a/src/dirfns.cc b/src/dirfns.cc --- a/src/dirfns.cc +++ b/src/dirfns.cc @@ -390,12 +390,8 @@ if (cmd && *cmd) { int ch; - ostrstream output_buf; while ((ch = cmd->get ()) != EOF) - output_buf << (char) ch; - output_buf << ends; - - maybe_page_output (output_buf); + octave_stdout << (char) ch; } else error ("couldn't start process for ls!"); @@ -426,11 +422,7 @@ if (! directory.empty ()) { if (nargout == 0) - { - ostrstream output_buf; - output_buf << directory << "\n" << ends; - maybe_page_output (output_buf); - } + octave_stdout << directory << "\n"; else retval = directory; } diff --git a/src/error.cc b/src/error.cc --- a/src/error.cc +++ b/src/error.cc @@ -53,7 +53,7 @@ static void verror (const char *name, const char *fmt, va_list args) { - flush_output_to_pager (); + flush_octave_stdout (); int to_beep_or_not_to_beep = user_pref.beep_on_error && ! error_state; @@ -91,7 +91,7 @@ } else { - maybe_write_to_diary_file (msg); + octave_diary << msg; cerr << msg; } @@ -185,7 +185,7 @@ void panic (const char *fmt, ...) { - flush_output_to_pager (); + flush_octave_stdout (); va_list args; va_start (args, fmt); diff --git a/src/file-io.cc b/src/file-io.cc --- a/src/file-io.cc +++ b/src/file-io.cc @@ -20,282 +20,129 @@ */ -// Written by John C. Campbell +// Originally written by John C. Campbell // -// Thomas Baier added the following functions: +// Thomas Baier added the original versions of +// the following functions: // -// popen pclose execute sync_system async_system -// waitpid mkfifo unlink +// popen +// pclose +// execute (now popen2.m) +// sync_system (now merged with system) +// async_system (now merged with system) +// Completely rewritten by John W. Eaton , +// April 1996. #ifdef HAVE_CONFIG_H #include #endif -#include -#include -#include -#include -#include +#include -#include - -#include +#include #ifdef HAVE_UNISTD_H #include #include #endif -#include - -#include -#include - -#include "dMatrix.h" - #include "defun.h" #include "error.h" -#include "file-info.h" -#include "file-io.h" #include "file-ops.h" #include "help.h" -#include "input.h" -#include "mappers.h" +#include "oct-fstrm.h" +#include "oct-iostrm.h" #include "oct-map.h" -#include "oct-hist.h" #include "oct-obj.h" +#include "oct-prcstrm.h" +#include "oct-stream.h" +#include "oct-strstrm.h" #include "pager.h" #include "sysdep.h" #include "syswait.h" #include "utils.h" -#include "variables.h" - -// keeps a count of args sent to printf or scanf -static int fmt_arg_count = 0; - -// double linked list containing relevant information about open files -static DLList file_list; - -// stack for next available file number -static SLStack next_available_file_number; - -static int -get_next_avail_file_num (void) -{ - if (next_available_file_number.empty ()) - return file_list.length (); - else - return next_available_file_number.pop (); -} void initialize_file_io (void) { - file_info octave_stdin (0, "stdin", stdin, "r"); - file_info octave_stdout (1, "stdout", stdout, "w"); - file_info octave_stderr (2, "stderr", stderr, "w"); + octave_istream *stdin_stream = new octave_istream (&cin, "stdin"); + octave_ostream *stdout_stream = new octave_ostream (&cout, "stdout"); + octave_ostream *stderr_stream = new octave_ostream (&cerr, "stderr"); - file_list.append (octave_stdin); - file_list.append (octave_stdout); - file_list.append (octave_stderr); + octave_stream_list::insert (stdin_stream); + octave_stream_list::insert (stdout_stream); + octave_stream_list::insert (stderr_stream); } -// Given a file name or number, return a pointer to the corresponding -// open file. If the file has not already been opened, return NULL. - -Pix -return_valid_file (const tree_constant& arg) +void +close_files (void) { - if (arg.is_string ()) - { - Pix p = file_list.first (); - file_info file; - int file_count = file_list.length (); - for (int i = 0; i < file_count; i++) - { - string file_name = arg.string_value (); - file = file_list (p); - if (file.name () == file_name) - return p; - file_list.next (p); - } - } - else - { - double file_num = arg.double_value (); + octave_stream_list::clear (); +} - if (! error_state) - { - if (D_NINT (file_num) != file_num) - error ("file number not an integer value"); - else - { - Pix p = file_list.first (); - file_info file; - int file_count = file_list.length (); - for (int i = 0; i < file_count; i++) - { - file = file_list (p); - if (file.number () == file_num) - return p; - file_list.next (p); - } - error ("no file with that number"); - } - } - else - error ("inapproriate file specifier"); - } - - return 0; +static void +gripe_invalid_file_id (const char *fcn) +{ + ::error ("%s: invalid file id", fcn); } -static Pix -fopen_file_for_user (const string& name, const char *mode, - const char *warn_for) +static int +fopen_mode_to_ios_mode (const string& mode) { - FILE *file_ptr = fopen (name.c_str (), mode); - if (file_ptr) - { - int file_number = get_next_avail_file_num (); + int retval = 0; - file_info file (file_number, name, file_ptr, mode); - file_list.append (file); - - Pix p = file_list.first (); - file_info file_from_list; - int file_count = file_list.length (); - for (int i = 0; i < file_count; i++) - { - file_from_list = file_list (p); - if (file_from_list.name () == name) - return p; - file_list.next (p); - } - } - - error ("%s: unable to open file `%s'", warn_for, name.c_str ()); - - return 0; -} - -static Pix -file_io_get_file (const tree_constant& arg, const char *mode, - const char *warn_for) -{ - Pix p = return_valid_file (arg); - - if (! p) + if (! mode.empty ()) { - if (arg.is_string ()) - { - string name = arg.string_value (); - - file_stat fs (name); + // Could probably be faster, but does it really matter? - if (fs) - { - if (fs.is_reg ()) - p = fopen_file_for_user (name, mode, warn_for); - else - error ("%s: invalid file type", warn_for); - } - else - { - if (*mode != 'r') - p = fopen_file_for_user (name, mode, warn_for); - else - error ("%s: can't stat file `%s'", warn_for, name.c_str ()); - } - } + if (mode == "r") + retval = ios::in; + else if (mode == "w") + retval = ios::out | ios::trunc; + else if (mode == "a") + retval = ios::out | ios::app; + else if (mode == "r+") + retval = ios::in | ios::out; + else if (mode == "w+") + retval = ios::in | ios::out | ios::trunc; + else if (mode == "a+") + retval = ios::in | ios::out | ios::app; + else if (mode == "rb") + retval = ios::in | ios::bin; + else if (mode == "wb") + retval = ios::out | ios::trunc | ios::bin; + else if (mode == "ab") + retval = ios::out | ios::app | ios::bin; + else if (mode == "r+b") + retval = ios::in | ios::out | ios::bin; + else if (mode == "w+b") + retval = ios::in | ios::out | ios::trunc | ios::bin; + else if (mode == "a+b") + retval = ios::in | ios::out | ios::app | ios::bin; else - error ("%s: invalid file specifier", warn_for); - } - - return p; -} - -static Octave_object -fclose_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 ("fclose: can't close stdin, stdout, or stderr!"); - return retval; - } - - int success = fclose (file.fptr ()); - next_available_file_number.push (file.number ()); - file_list.del (p); - - if (success == 0) - retval(0) = 1.0; // succeeded - else - { - error ("fclose: error on closing file"); - retval(0) = 0.0; // failed + ::error ("invalid mode specified"); } return retval; } DEFUN (fclose, args, , - "fclose (FILENAME or FILENUM): close a file") + "fclose (FILENAME or FILENUM): close a file") { - Octave_object retval; + double retval = -1.0; int nargin = args.length (); - if (nargin != 1) - print_usage ("fclose"); - else - retval = fclose_internal (args); - - return retval; -} - -static Octave_object -fflush_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 (nargin == 1) + { + retval = (double) octave_stream_list::remove (args(0)); - if (file.mode () == "r") - { - warning ("can't flush an input stream"); - return retval; + if (retval < 0) + gripe_invalid_file_id ("fclose"); } - - int success = 0; - - if (file.number () == 1) - flush_output_to_pager (); else - success = fflush (file.fptr ()); - - if (success == 0) - retval(0) = 1.0; // succeeded - else - { - error ("fflush: write error"); - retval(0) = 0.0; // failed - } + print_usage ("fclose"); return retval; } @@ -303,263 +150,217 @@ DEFUN (fflush, args, , "fflush (FILENAME or FILENUM): flush buffered data to output file") { - Octave_object retval; + double retval = -1.0; int nargin = args.length (); - if (nargin != 1) + if (nargin == 1) + { + octave_stream *os = octave_stream_list::lookup (args(0)); + + if (os) + retval = (double) os->flush (); + else + gripe_invalid_file_id ("fflush"); + } + else print_usage ("fflush"); - else - retval = fflush_internal (args); return retval; } -static int -valid_mode (const string& mode) -{ - if (! mode.empty ()) - { - char m = mode[0]; - if (m == 'r' || m == 'w' || m == 'a') - return (mode.length () == 2) ? mode[1] == '+' : 1; - } - return 0; -} - -static Octave_object -fgets_internal (const Octave_object& args, int nargin, int nargout, - int strip_final_newline = 0) -{ - Octave_object retval; - - Pix p = file_io_get_file (args(0), "r", "fgets"); - - if (! p) - return retval; - - int length = 0; - - if (nargin == 2) - { - double dlen = args(1).double_value (); - - if (error_state) - return retval; - - if (xisnan (dlen)) - { - error ("fgets: NaN invalid as length"); - return retval; - } - - length = NINT (dlen); - - if ((double) length != dlen) - { - error ("fgets: length not an integer value"); - return retval; - } - - if (length < 0) - { - error ("fgets: length must be a nonnegative integer"); - return retval; - } - } - - file_info file = file_list (p); - FILE *fileptr = file.fptr (); - - ostrstream buf; - int c; - int count = 0; - int newline_stripped = 0; - - if (nargin == 1 || length > 0) - { - while ((c = fgetc (fileptr)) != EOF) - { - count++; - if (c == '\n') - { - if (! strip_final_newline) - buf << (char) c; - else - newline_stripped = 1; - - break; - } - else - buf << (char) c; - - if (nargin == 2 && count == length) - break; - } - } - - buf << ends; - char *string = buf.str (); - - if (count) - { - if (nargout == 2) - retval(1) = (double) (count - newline_stripped); - - retval(0) = string; - } - else - retval(0) = -1.0; - - delete [] string; - - return retval; -} - -DEFUN (fgetl, args, nargout, - "[STRING, LENGTH] = fgetl (FILENAME or FILENUM [, LENGTH])\n\ +DEFUN (fgetl, args, , + "STRING = fgetl (FILENAME or FILENUM [, LENGTH])\n\ \n\ read a string from a file") { - Octave_object retval; + octave_value retval = -1.0; int nargin = args.length (); if (nargin == 1 || nargin == 2) - retval = fgets_internal (args, nargin, nargout, 1); + { + octave_stream *os = octave_stream_list::lookup (args(0)); + + if (os) + { + octave_value len_arg = (nargin == 2) + ? args(1) : octave_value ((double) INT_MAX); + + bool err = false; + + string tmp = os->getl (len_arg, err); + + if (! err) + retval = tmp; + } + else + gripe_invalid_file_id ("fgetl"); + } else print_usage ("fgetl"); return retval; } -DEFUN (fgets, args, nargout, - "[STRING, LENGTH] = fgets (FILENAME or FILENUM [, LENGTH])\n\ +DEFUN (fgets, args, , + "STRING = fgets (FILENAME or FILENUM [, LENGTH])\n\ \n\ read a string from a file") { - Octave_object retval; + octave_value retval = -1.0; int nargin = args.length (); if (nargin == 1 || nargin == 2) - retval = fgets_internal (args, nargin, nargout); + { + octave_stream *os = octave_stream_list::lookup (args(0)); + + if (os) + { + octave_value len_arg = (nargin == 2) + ? args(1) : octave_value ((double) INT_MAX); + + bool err = false; + + string tmp = os->gets (len_arg, err); + + if (! err) + retval = tmp; + } + else + gripe_invalid_file_id ("fgets"); + } else print_usage ("fgets"); return retval; } -static Octave_object -fopen_internal (const Octave_object& args) +static octave_base_stream * +do_stream_open (const string& name, const string& mode, + const string& arch, int& fid) { - Octave_object retval; - Pix p; + octave_base_stream *retval = 0; - if (! args(0).is_string ()) - { - error ("fopen: file name must be a string"); - return retval; - } - - p = return_valid_file (args(0)); + fid = -1; - if (p) - { - file_info file = file_list (p); - - retval(0) = (double) file.number (); + int md = fopen_mode_to_ios_mode (mode); - return retval; - } + if (! error_state) + { + octave_base_stream::arch_type at = octave_stream::string_to_arch (arch); - if (! args(1).is_string ()) - { - error ("fopen: file mode must be a string"); - return retval; + if (! error_state) + retval = new octave_fstream (name, md, at); } - string name = args(0).string_value (); - string mode = args(1).string_value (); + return retval; +} - if (! valid_mode (mode)) +static octave_base_stream * +do_stream_open (const octave_value& tc_name, const octave_value& tc_mode, + const octave_value& tc_arch, const char *fcn, int& fid) +{ + octave_base_stream *retval = 0; + + fid = -1; + + string name = tc_name.string_value (); + + if (! error_state) { - error ("fopen: invalid mode"); - return retval; - } + string mode = tc_mode.string_value (); + + if (! error_state) + { + string arch = tc_arch.string_value (); - file_stat fs (name); - - if (fs && fs.is_dir ()) - { - error ("fopen: can't open directory"); - return retval; + if (! error_state) + retval = do_stream_open (name, mode, arch, fid); + else + ::error ("%s: architecture type must be a string", fcn); + } + else + ::error ("%s: file mode must be a string", fcn); } - - FILE *file_ptr = fopen (name.c_str (), mode.c_str ()); - - if (! file_ptr) - { - error ("fopen: unable to open file `%s'", name.c_str ()); - return retval; - } - - int file_number = get_next_avail_file_num (); - - file_info file (file_number, name, file_ptr, mode); - file_list.append (file); - - retval(0) = (double) file_number; + else + ::error ("%s: file name must be a string", fcn); return retval; } DEFUN (fopen, args, , - "FILENUM = fopen (FILENAME, MODE): open a file\n\ + "FILENUM = fopen (FILENAME, MODE [, ARCH]): open a file\n\ \n\ Valid values for mode include:\n\ \n\ - r : open text file for reading\n\ - w : open text file for writing; discard previous contents if any\n\ - a : append; open or create text file for writing at end of file\n\ - r+ : open text file for update (i.e., reading and writing)\n\ - w+ : create text file for update; discard previous contents if any\n\ - a+ : append; open or create text file for update, writing at end\n\n\ - Update mode permits reading from and writing to the same file.") + r : open text file for reading\n\ + w : open text file for writing; discard previous contents if any\n\ + a : append; open or create text file for writing at end of file\n\ + r+ : open text file for update (i.e., reading and writing)\n\ + w+ : create text file for update; discard previous contents if any\n\ + a+ : append; open or create text file for update, writing at end\n\ +\n\ + Update mode permits reading from and writing to the same file.") { - Octave_object retval; + octave_value_list retval = -1.0; int nargin = args.length (); - if (nargin != 2) - print_usage ("fopen"); - else - retval = fopen_internal (args); - - return retval; -} + if (nargin == 1) + { + if (args(0).is_string () && args(0).string_value () == "all") + { + return octave_stream_list::open_file_numbers (); + } + else + { + string_vector tmp = octave_stream_list::get_info (args(0)); -static Octave_object -freport_internal (void) -{ - Octave_object retval; - Pix p = file_list.first (); - - ostrstream output_buf; + if (! error_state) + { + retval(2) = tmp(2); + retval(1) = tmp(1); + retval(0) = tmp(0); + } - output_buf << "\n number mode name\n\n"; - - int file_count = file_list.length (); - for (int i = 0; i < file_count; i++) - { - file_info file = file_list (p); - output_buf.form ("%7d%6s %s\n", file.number (), - file.mode ().c_str (), file.name ().c_str ()); - file_list.next (p); + return retval; + } } - output_buf << "\n" << ends; - maybe_page_output (output_buf); + if (nargin > 0 && nargin < 4) + { + octave_value mode = (nargin == 2 || nargin == 3) + ? args(1) : octave_value ("r"); + + octave_value arch = (nargin == 3) + ? args(2) : octave_value ("native"); + + int fid = -1; + + octave_base_stream *os + = do_stream_open (args(0), mode, arch, "fopen", fid); + + if (os) + { + if (os->ok () && ! error_state) + { + retval(1) = ""; + retval(0) = (double) octave_stream_list::insert (os); + } + else + { + int errno = 0; + retval(1) = os->error (false, errno); + retval(0) = -1.0; + } + } + else + ::error ("fopen: internal error"); + } + else + print_usage ("fopen"); return retval; } @@ -567,30 +368,14 @@ DEFUN (freport, args, , "freport (): list open files and their status") { - Octave_object retval; + octave_value_list retval; int nargin = args.length (); if (nargin > 0) warning ("freport: ignoring extra arguments"); - retval = freport_internal (); - - return retval; -} - -static Octave_object -frewind_internal (const Octave_object& args) -{ - Octave_object retval; - - Pix p = file_io_get_file (args(0), "a+", "frewind"); - - if (p) - { - file_info file = file_list (p); - rewind (file.fptr ()); - } + octave_stdout << octave_stream_list::list_open_files (); return retval; } @@ -598,95 +383,21 @@ DEFUN (frewind, args, , "frewind (FILENAME or FILENUM): set file position at beginning of file") { - Octave_object retval; - - int nargin = args.length (); - - if (nargin != 1) - print_usage ("frewind"); - else - retval = frewind_internal (args); - - return retval; -} - -static Octave_object -fseek_internal (const Octave_object& args) -{ - Octave_object retval; + double retval = -1.0; int nargin = args.length (); - Pix p = file_io_get_file (args(0), "a+", "fseek"); - - if (! p) - return retval; - - long origin = SEEK_SET; - - double doff = args(1).double_value (); - - if (error_state) - return retval; - - if (xisnan (doff)) + if (nargin == 1) { - error ("fseek: NaN invalid as offset"); - return retval; - } - - long offset = NINT (doff); - - if ((double) offset != doff) - { - error ("fseek: offset not an integer value"); - return retval; - } - - if (nargin == 3) - { - double dorig = args(2).double_value (); - - if (error_state) - return retval; + octave_stream *os = octave_stream_list::lookup (args(0)); - if (xisnan (dorig)) - { - error ("fseek: NaN invalid as origin"); - return retval; - } - - origin = NINT (dorig); - - if ((double) dorig != origin) - { - error ("fseek: origin not an integer value"); - return retval; - } - - if (origin == 0) - origin = SEEK_SET; - else if (origin == 1) - origin = SEEK_CUR; - else if (origin == 2) - origin = SEEK_END; + if (os) + retval = (double) os->rewind (); else - { - error ("fseek: invalid value for origin"); - return retval; - } + gripe_invalid_file_id ("frewind"); } - - file_info file = file_list (p); - int success = fseek (file.fptr (), offset, origin); - - if (success == 0) - retval(0) = 1.0; // succeeded else - { - error ("fseek: file error"); - retval(0) = 0.0; // failed - } + print_usage ("frewind"); return retval; } @@ -696,37 +407,26 @@ \n\ set file position for reading or writing") { - Octave_object retval; + double retval = -1.0; int nargin = args.length (); - if (nargin != 2 && nargin != 3) - print_usage ("fseek"); - else - retval = fseek_internal (args); - - return retval; -} - -// Tell current position of file. + if (nargin == 2 || nargin == 3) + { + octave_stream *os = octave_stream_list::lookup (args(0)); -static Octave_object -ftell_internal (const Octave_object& args) -{ - Octave_object retval; - - Pix p = file_io_get_file (args(0), "a+", "ftell"); + if (os) + { + octave_value origin_arg = (nargin == 3) + ? args(2) : octave_value (0.0); - if (p) - { - file_info file = file_list (p); - long offset = ftell (file.fptr ()); - - retval(0) = (double) offset; - - if (offset == -1L) - error ("ftell: write error"); + retval = (double) os->seek (args(1), origin_arg); + } + else + ::error ("fseek: invalid file id"); } + else + print_usage ("fseek"); return retval; } @@ -734,355 +434,21 @@ DEFUN (ftell, args, , "POSITION = ftell (FILENAME or FILENUM): returns the current file position") { - Octave_object retval; - - int nargin = args.length (); - - if (nargin != 1) - print_usage ("ftell"); - else - retval = ftell_internal (args); - - return retval; -} - -void -close_files (void) -{ - Pix p = file_list.first (); - - int file_count = file_list.length (); - for (int i = 0; i < file_count; i++) - { - if (p) - { - file_info file = file_list (p); - - if (i > 2) // do not close stdin, stdout, stderr! - { - int success = fclose (file.fptr ()); - if (success != 0) - error ("closing %s", file.name ().c_str ()); - } - - next_available_file_number.push (file.number ()); - file_list.del (p); - } - else - { - error ("inconsistent state for internal file list!"); - break; - } - } -} - -static int -process_printf_format (const char *s, const Octave_object& args, - ostrstream& sb, const char *type) -{ - ostrstream fmt; + double retval = -1.0; int nargin = args.length (); - fmt << "%"; // do_printf() already blew past this one... - - int chars_from_fmt_str = 0; - - again: - switch (*s) + if (nargin == 1) { - case '+': case '-': case ' ': case '0': case '#': - chars_from_fmt_str++; - fmt << *s++; - goto again; - - case '\0': - goto invalid_format; - - default: - break; - } - - if (*s == '*') - { - if (fmt_arg_count > nargin) - { - error ("%s: not enough arguments", type); - return -1; - } - - double tmp_len = args(fmt_arg_count++).double_value (); - - if (error_state || xisnan (tmp_len)) - { - error ("%s: `*' must be replaced by an integer", type); - return -1; - } + octave_stream *os = octave_stream_list::lookup (args(0)); - fmt << NINT (tmp_len); - s++; - chars_from_fmt_str++; - } - else - { - while (*s != '\0' && isdigit (*s)) - { - chars_from_fmt_str++; - fmt << *s++; - } - } - - if (*s == '\0') - goto invalid_format; - - if (*s == '.') - { - chars_from_fmt_str++; - fmt << *s++; - } - - if (*s == '*') - { - if (*(s-1) == '*') - goto invalid_format; - - if (fmt_arg_count > nargin) - { - error ("%s: not enough arguments", type); - return -1; - } - - double tmp_len = args(fmt_arg_count++).double_value (); - - if (error_state || xisnan (tmp_len)) - { - error ("%s: `*' must be replaced by an integer", type); - return -1; - } - - fmt << NINT (tmp_len); - s++; - chars_from_fmt_str++; + if (os) + retval = (double) os->tell (); + else + gripe_invalid_file_id ("ftell"); } else - { - while (*s != '\0' && isdigit (*s)) - { - chars_from_fmt_str++; - fmt << *s++; - } - } - - if (*s == '\0') - goto invalid_format; - - if (*s != '\0' && (*s == 'h' || *s == 'l' || *s == 'L')) - { - chars_from_fmt_str++; - fmt << *s++; - } - - if (*s == '\0') - goto invalid_format; - - if (fmt_arg_count > nargin) - { - error ("%s: not enough arguments", type); - return -1; - } - - switch (*s) - { - case 'd': case 'i': case 'o': case 'u': case 'x': case 'X': - { - double d = args(fmt_arg_count++).double_value (); - - if (error_state || xisnan (d)) - goto invalid_conversion; - - int val = NINT (d); - - if ((double) val != d) - goto invalid_conversion; - else - { - chars_from_fmt_str++; - fmt << *s << ends; - char *tmp_fmt = fmt.str (); - sb.form (tmp_fmt, val); - delete [] tmp_fmt; - return chars_from_fmt_str; - } - } - - case 'e': case 'E': case 'f': case 'g': case 'G': - { - double val = args(fmt_arg_count++).double_value (); - - if (error_state) - goto invalid_conversion; - else - { - chars_from_fmt_str++; - fmt << *s << ends; - char *tmp_fmt = fmt.str (); - sb.form (tmp_fmt, val); - delete [] tmp_fmt; - return chars_from_fmt_str; - } - } - - case 's': - { - string val = args(fmt_arg_count++).string_value (); - - if (error_state) - goto invalid_conversion; - else - { - chars_from_fmt_str++; - fmt << *s << ends; - char *tmp_fmt = fmt.str (); - sb.form (tmp_fmt, val.c_str ()); - delete [] tmp_fmt; - return chars_from_fmt_str; - } - } - - case 'c': - { - string val = args(fmt_arg_count++).string_value (); - - if (error_state || val.length () != 1) - goto invalid_conversion; - else - { - chars_from_fmt_str++; - fmt << *s << ends; - char *tmp_fmt = fmt.str (); - sb.form (tmp_fmt, val[0]); - delete [] tmp_fmt; - return chars_from_fmt_str; - } - } - - default: - goto invalid_format; - } - - invalid_conversion: - error ("%s: invalid conversion", type); - return -1; - - invalid_format: - error ("%s: invalid format", type); - return -1; -} - -// Formatted printing to a file. - -static Octave_object -do_printf (const char *type, const Octave_object& args) -{ - Octave_object retval; - fmt_arg_count = 0; - const char *fmt; - string fmt_str; - file_info file; - - if (strcmp (type, "fprintf") == 0) - { - Pix p = file_io_get_file (args(0), "a+", type); - - if (! p) - return retval; - - file = file_list (p); - - if (file.mode () == "r") - { - error ("%s: file is read only", type); - return retval; - } - - fmt_str = args(1).string_value (); - fmt = fmt_str.c_str (); - - if (error_state) - { - error ("%s: format must be a string", type); - return retval; - } - - fmt_arg_count += 2; - } - else - { - fmt_str = args(0).string_value (); - fmt = fmt_str.c_str (); - - if (error_state) - { - error ("%s: invalid format string", type); - return retval; - } - - fmt_arg_count++; - } - - // Scan fmt for % escapes and print out the arguments. - - ostrstream output_buf; - - const char *ptr = fmt; - - for (;;) - { - char c; - while ((c = *ptr++) != '\0' && c != '%') - output_buf << c; - - if (c == '\0') - break; - - if (*ptr == '%') - { - ptr++; - output_buf << c; - continue; - } - - // We must be looking at a format specifier. Extract it or - // fail. - - int status = process_printf_format (ptr, args, output_buf, type); - - if (status < 0) - return retval; - - ptr += status; - } - - output_buf << ends; - if (strcmp (type, "printf") == 0 - || (strcmp (type, "fprintf") == 0 && file.number () == 1)) - { - maybe_page_output (output_buf); - } - else if (strcmp (type, "fprintf") == 0) - { - char *msg = output_buf.str (); - int success = fputs (msg, file.fptr ()); - if (success == EOF) - warning ("%s: unknown failure writing to file", type); - delete [] msg; - } - else if (strcmp (type, "sprintf") == 0) - { - char *msg = output_buf.str (); - retval(0) = msg; - delete [] msg; - } + print_usage ("ftell"); return retval; } @@ -1090,639 +456,212 @@ DEFUN (fprintf, args, , "fprintf (FILENAME or FILENUM, FORMAT, ...)") { - Octave_object retval; + double retval = -1.0; int nargin = args.length (); - if (nargin < 2) + if (nargin > 1) + { + octave_stream *os = octave_stream_list::lookup (args(0)); + + if (os) + { + if (args(1).is_string ()) + { + string fmt = args(1).string_value (); + + octave_value_list tmp_args; + + if (nargin > 2) + { + tmp_args.resize (nargin-2, octave_value ()); + + for (int i = 2; i < nargin; i++) + tmp_args(i-2) = args(i); + } + + retval = os->printf (fmt, tmp_args); + } + else + ::error ("fprintf: format must be a string"); + } + else + gripe_invalid_file_id ("fprintf"); + } + else print_usage ("fprintf"); - else - retval = do_printf ("fprintf", args); return retval; } -// Formatted printing. - -DEFUN (printf, args, , - "printf (FORMAT, ...)") +DEFUN (fputs, args, , + "fputs (FILENAME or FILENUM, STRING)") { - Octave_object retval; + double retval = -1.0; int nargin = args.length (); - if (nargin < 1) - print_usage ("printf"); - else - retval = do_printf ("printf", args); - - return retval; -} - -// Formatted printing to a string. + if (nargin == 2) + { + octave_stream *os = octave_stream_list::lookup (args(0)); -DEFUN (sprintf, args, , - "s = sprintf (FORMAT, ...)") -{ - Octave_object retval; - - int nargin = args.length (); - - if (nargin < 1) - print_usage ("sprintf"); + if (os) + retval = os->puts (args(1)); + else + gripe_invalid_file_id ("fputs"); + } else - retval = do_printf ("sprintf", args); + print_usage ("fputs"); return retval; } -static int -process_scanf_format (const char *s, ostrstream& fmt, - const char *type, int nargout, FILE* fptr, - Octave_object& values) +DEFUN (sprintf, args, , + "[s, errmsg, status] = sprintf (FORMAT, ...)") { - fmt << "%"; + octave_value_list retval; - int chars_from_fmt_str = 0; - int store_value = 1; - int string_width = 0; - int success = 1; + retval(2) = -1.0; + retval(1) = "unknown error"; + retval(0) = ""; - if (*s == '*') - { - store_value = 0; - s++; - chars_from_fmt_str++; - } + int nargin = args.length (); - if (isdigit (*s)) + if (nargin > 0) { - ostrstream str_number; - while (*s != '\0' && isdigit (*s)) - { - chars_from_fmt_str++; - str_number << *s; - fmt << *s++; - } - str_number << ends; - char *number = str_number.str (); - string_width = atoi (number); - delete [] number; - } - - if (*s == '\0') - goto invalid_format; - - if (*s != '\0' && (*s == 'h' || *s == 'l' || *s == 'L')) - { - chars_from_fmt_str++; - s++; - } + octave_ostrstream ostr; - if (*s == '\0') - goto invalid_format; - - // Even if we don't have a place to store them, attempt to convert - // everything specified by the format string. - - if (fmt_arg_count > (nargout ? nargout : 1)) - store_value = 0; - - switch (*s) - { - case 'd': case 'i': case 'o': case 'u': case 'x': case 'X': - { - chars_from_fmt_str++; - fmt << *s << ends; - int temp; - char *str = fmt.str (); - success = fscanf (fptr, str, &temp); - delete [] str; - if (success > 0 && store_value) - values(fmt_arg_count++) = (double) temp; - } - break; + octave_stream os (&ostr); - case 'e': case 'E': case 'f': case 'g': case 'G': - { - chars_from_fmt_str++; - fmt << 'l' << *s << ends; - double temp; - char *str = fmt.str (); - success = fscanf (fptr, str, &temp); - delete [] str; - if (success > 0 && store_value) - values(fmt_arg_count++) = temp; - } - break; + if (os) + { + if (args(0).is_string ()) + { + string fmt = args(0).string_value (); - case 's': - { - if (string_width < 1) - { - // XXX FIXME XXX -- The code below is miscompiled on the - // Alpha with gcc 2.6.0, so that string_width is never - // incremented, even though reading the data works - // correctly. One fix is to use a fixed-size buffer... -// string_width = 8192; - - string_width = 0; - long original_position = ftell (fptr); - - int c; + octave_value_list tmp_args; - while ((c = getc (fptr)) != EOF && isspace (c)) - ; // Don't count leading whitespace. - - if (c != EOF) - string_width++; - - for (;;) - { - c = getc (fptr); - if (c != EOF && ! isspace (c)) - string_width++; - else - break; - } + if (nargin > 1) + { + tmp_args.resize (nargin-1, octave_value ()); - fseek (fptr, original_position, SEEK_SET); - } - chars_from_fmt_str++; - char temp [string_width+1]; - fmt << *s << ends; - char *str = fmt.str (); - success = fscanf (fptr, str, temp); - delete [] str; - temp[string_width] = '\0'; - if (success > 0 && store_value) - values(fmt_arg_count++) = temp; - } - break; + for (int i = 1; i < nargin; i++) + tmp_args(i-1) = args(i); + } - case 'c': - { - if (string_width < 1) - string_width = 1; - chars_from_fmt_str++; - char temp [string_width+1]; - memset (temp, '\0', string_width+1); - fmt << *s << ends; - char *str = fmt.str (); - success = fscanf (fptr, str, temp); - delete [] str; - temp[string_width] = '\0'; - if (success > 0 && store_value) - values(fmt_arg_count++) = temp; - } - break; - - default: - goto invalid_format; - } - - if (success > 0) - return chars_from_fmt_str; - else if (success == 0) - warning ("%s: invalid conversion", type); - else if (success == EOF) - { - if (strcmp (type, "fscanf") == 0) - warning ("%s: end of file reached before final conversion", type); - else if (strcmp (type, "sscanf") == 0) - warning ("%s: end of string reached before final conversion", type); - else if (strcmp (type, "scanf") == 0) - warning ("%s: end of input reached before final conversion", type); + retval(2) = os.printf (fmt, tmp_args); + retval(1) = os.error (); + char *tmp = ostr.str (); + retval(0) = tmp; + delete [] tmp; + } + else + ::error ("sprintf: format must be a string"); + } + else + ::error ("sprintf: unable to create output buffer"); } else - { - invalid_format: - warning ("%s: invalid format", type); - } - - return -1; -} - -// Formatted reading from a file. - -static Octave_object -do_scanf (const char *type, const Octave_object& args, int nargout) -{ - Octave_object retval; - const char *scanf_fmt = 0; - string scanf_fmt_str; - string tmp_file; - int tmp_file_open = 0; - FILE *fptr = 0; - file_info file; - - fmt_arg_count = 0; - - if (strcmp (type, "scanf") != 0) - { - scanf_fmt_str = args(1).string_value (); - scanf_fmt = scanf_fmt_str.c_str (); - - if (error_state) - { - error ("%s: format must be a string", type); - return retval; - } - } - - int doing_fscanf = (strcmp (type, "fscanf") == 0); - - if (doing_fscanf) - { - Pix p = file_io_get_file (args(0), "r", type); - - if (! p) - return retval; - - file = file_list (p); - - if (file.mode () == "w" || file.mode () == "a") - { - error ("%s: this file is opened for writing only", type); - return retval; - } - - fptr = file.fptr (); - } - - if ((! fptr && args(0).is_string ()) - || (doing_fscanf && file.number () == 0)) - { - string xstring_str; - const char *xstring; - - if (strcmp (type, "scanf") == 0) - { - scanf_fmt_str = args(0).string_value (); - scanf_fmt = scanf_fmt_str.c_str (); - } - - if (strcmp (type, "scanf") == 0 - || (doing_fscanf && file.number () == 0)) - { - // XXX FIXME XXX -- this should probably be possible for - // more than just stdin/stdout pairs, using a list of output - // streams to flush. The list could be created with a - // function like iostream's tie(). - - flush_output_to_pager (); - - xstring = gnu_readline (""); - - if (xstring && *xstring) - octave_command_history.add (xstring); - } - else - { - xstring_str = args(0).string_value (); - xstring = xstring_str.c_str (); - } - - tmp_file = oct_tempnam (); - - fptr = fopen (tmp_file.c_str (), "w+"); - if (! fptr) - { - error ("%s: error opening temporary file", type); - return retval; - } - tmp_file_open = 1; - unlink (tmp_file.c_str ()); - - if (! xstring) - { - error ("%s: no string to scan", type); - return retval; - } - - int success = fputs (xstring, fptr); - fflush (fptr); - rewind (fptr); - - if (success < 0) - { - error ("%s: trouble writing temporary file", type); - fclose (fptr); - return retval; - } - } - else if (! doing_fscanf) - { - error ("%s: first argument must be a string", type); - return retval; - } - - // Scan scanf_fmt for % escapes and assign the arguments. - - retval.resize (nargout); - - const char *ptr = scanf_fmt; - - for (;;) - { - ostrstream fmt; - char c; - while ((c = *ptr++) != '\0' && c != '%') - fmt << c; - - if (c == '\0') - break; - - if (*ptr == '%') - { - ptr++; - fmt << c; - continue; - } - - // We must be looking at a format specifier. Extract it or - // fail. - - int status = process_scanf_format (ptr, fmt, type, nargout, - fptr, retval); - - if (status < 0) - { - if (fmt_arg_count == 0) - retval.resize (0); - break; - } - - ptr += status; - } - - if (tmp_file_open) - fclose (fptr); + print_usage ("sprintf"); return retval; } -DEFUN (fscanf, args, nargout, - "[A, B, C, ...] = fscanf (FILENAME or FILENUM, FORMAT)") +DEFUN (fscanf, args, , + "[A, B, C, ...] = fscanf (FILENAME or FILENUM, FORMAT, SIZE)") { - Octave_object retval; + octave_value_list retval; int nargin = args.length (); - if (nargin != 1 && nargin != 2) - print_usage ("fscanf"); - else - retval = do_scanf ("fscanf", args, nargout); - - return retval; -} + if (nargin == 2 || nargin == 3) + { + octave_stream *os = octave_stream_list::lookup (args(0)); -// Formatted reading. + if (os) + { + if (args(1).is_string ()) + { + string fmt = args(1).string_value (); -DEFUN (scanf, args, nargout, - "[A, B, C, ...] = scanf (FORMAT)") -{ - Octave_object retval; - - int nargin = args.length (); + int count = 0; - if (nargin != 1) - print_usage ("scanf"); - else - retval = do_scanf ("scanf", args, nargout); + // XXX FIXME XXX + Array size (2); - return retval; -} - -// Formatted reading from a string. + octave_value tmp = os->scanf (fmt, size, count); -DEFUN (sscanf, args, nargout, - "[A, B, C, ...] = sscanf (STRING, FORMAT)") -{ - Octave_object retval; - - int nargin = args.length (); - - if (nargin != 2) - print_usage ("sscanf"); + retval(1) = (double) count; + retval(0) = tmp; + } + else + ::error ("fscanf: format must be a string"); + } + else + gripe_invalid_file_id ("fscanf"); + } else - retval = do_scanf ("sscanf", args, nargout); + print_usage ("fscanf"); return retval; } -// Find out how many elements are left to read. - -static long -num_items_remaining (FILE *fptr, const char *type) +DEFUN (sscanf, args, , + "[A, COUNT, ERRMSG, INDEX] = sscanf (STRING, FORMAT, SIZE)") { - size_t size; - - if (strcasecmp (type, "uchar") == 0) - size = sizeof (u_char); - else if (strcasecmp (type, "char") == 0) - size = sizeof (char); - else if (strcasecmp (type, "short") == 0) - size = sizeof (short); - else if (strcasecmp (type, "ushort") == 0) - size = sizeof (u_short); - else if (strcasecmp (type, "int") == 0) - size = sizeof (int); - else if (strcasecmp (type, "uint") == 0) - size = sizeof (u_int); - else if (strcasecmp (type, "long") == 0) - size = sizeof (long); - else if (strcasecmp (type, "ulong") == 0) - size = sizeof (u_long); - else if (strcasecmp (type, "float") == 0) - size = sizeof (float); - else if (strcasecmp (type, "double") == 0) - size = sizeof (double); - else - return 0; - - long curr_pos = ftell (fptr); + octave_value_list retval; - fseek (fptr, 0, SEEK_END); - long end_of_file = ftell (fptr); - - fseek (fptr, curr_pos, SEEK_SET); - - long len = end_of_file - curr_pos; - - return len / size; -} - -// Read binary data from a file. -// -// [data, count] = fread (fid, size, 'precision') -// -// fid : the file id from fopen -// size : the size of the matrix or vector or scaler to read -// -// n : reads n elements of a column vector -// inf : reads to the end of file (default) -// [m, n] : reads enough elements to fill the matrix -// the number of columns can be inf -// -// precision : type of the element. Can be: -// -// char, uchar, schar, short, ushort, int, uint, -// long, ulong, float, double -// -// Default is uchar. -// -// data : output data -// count : number of elements read - -static Octave_object -fread_internal (const Octave_object& args, int nargout) -{ - Octave_object retval; + retval(3) = -1.0; + retval(2) = "unknown error"; + retval(1) = 0.0; + retval(0) = Matrix (); int nargin = args.length (); - Pix p = file_io_get_file (args(0), "r", "fread"); + if (nargin == 2 || nargin == 3) + { + if (args(0).is_string ()) + { + string data = args(0).string_value (); - if (! p) - return retval; - - // Get type and number of bytes per element to read. + octave_istrstream istr (data); - const char *prec = "uchar"; - string tstr; - if (nargin > 2) - { - tstr = args(2).string_value (); - prec = tstr.c_str (); + octave_stream os (&istr); - if (error_state) - { - error ("fread: precision must be a specified as a string"); - return retval; - } - } + if (os) + { + if (args(1).is_string ()) + { + string fmt = args(1).string_value (); - file_info file = file_list (p); + int count = 0; - FILE *fptr = file.fptr (); + // XXX FIXME XXX + Array size (2); - // Set up matrix to read into. If specified in arguments use that - // number, otherwise read everyting left in file. + octave_value tmp = os.scanf (fmt, size, count); - double dnr = 0.0; - double dnc = 0.0; - int nr; - int nc; - - if (nargin > 1) - { - if (args(1).is_scalar_type ()) - { - dnr = args(1).double_value (); - - if (error_state) - return retval; - - dnc = 1.0; + retval(3) = (double) (os.tell () + 1); + retval(2) = os.error (); + retval(1) = (double) count; + retval(0) = tmp; + } + else + ::error ("sscanf: format must be a string"); + } + else + ::error ("sscanf: unable to create temporary input buffer"); } else - { - ColumnVector tmp = args(1).vector_value (); - - if (error_state || tmp.length () != 2) - { - error ("fread: invalid size specification\n"); - return retval; - } - - dnr = tmp.elem (0); - dnc = tmp.elem (1); - } - - if ((xisinf (dnr)) && (xisinf (dnc))) - { - error ("fread: number of rows and columns cannot both be infinite"); - return retval; - } - - if (xisinf (dnr)) - { - if (xisnan (dnc)) - { - error ("fread: NaN invalid as the number of columns"); - return retval; - } - else - { - nc = NINT (dnc); - int n = num_items_remaining (fptr, prec); - nr = n / nc; - if (n > nr * nc) - nr++; - } - } - else if (xisinf (dnc)) - { - if (xisnan (dnr)) - { - error ("fread: NaN invalid as the number of rows"); - return retval; - } - else - { - nr = NINT (dnr); - int n = num_items_remaining (fptr, prec); - nc = n / nr; - if (n > nc * nr) - nc++; - } - } - else - { - if (xisnan (dnr)) - { - error ("fread: NaN invalid as the number of rows"); - return retval; - } - else - nr = NINT (dnr); - - if (xisnan (dnc)) - { - error ("fread: NaN invalid as the number of columns"); - return retval; - } - else - nc = NINT (dnc); - } + ::error ("sscanf: first argument must be a string"); } else - { - // No size parameter, read what's left of the file. - - nc = 1; - int n = num_items_remaining (fptr, prec); - nr = n / nc; - if (n > nr * nc) - nr++; - } - - Matrix m (nr, nc, octave_NaN); - - // Read data. - - int count = m.read (fptr, prec); - - if (nargout > 1) - retval(1) = (double) count; - - retval(0) = m; + print_usage ("sscanf"); return retval; } -DEFUN (fread, args, nargout, +DEFUN (fread, , , "[DATA, COUNT] = fread (FILENUM, SIZE, PRECISION)\n\ \n\ Reads data in binary form of type PRECISION from a file.\n\ @@ -1737,76 +676,12 @@ DATA : matrix in which the data is stored\n\ COUNT : number of elements read") { - Octave_object retval; - - int nargin = args.length (); - - if (nargin < 1 || nargin > 3) - print_usage ("fread"); - else - retval = fread_internal (args, nargout); - + octave_value_list retval; + // XXX IMPLEMENTME XXX return retval; } -// Write binary data to a file. -// -// count = fwrite (fid, data, 'precision') -// -// fid : file id from fopen -// Data : data to be written -// precision : type of output element. Can be: -// -// char, uchar, schar, short, ushort, int, uint, -// long, float, double -// -// Default is uchar. -// -// count : the number of elements written - -static Octave_object -fwrite_internal (const Octave_object& args) -{ - Octave_object retval; - - int nargin = args.length (); - - Pix p = file_io_get_file (args(0), "a+", "fwrite"); - - if (! p) - return retval; - - // Get type and number of bytes per element to read. - - const char *prec = "uchar"; - string tstr; - if (nargin > 2) - { - tstr = args(2).string_value (); - prec = tstr.c_str (); - - if (error_state) - { - error ("fwrite: precision must be a specified as a string"); - return retval; - } - } - - file_info file = file_list (p); - - Matrix m = args(1).matrix_value (); - - if (! error_state) - { - int count = m.write (file.fptr (), prec); - - retval(0) = (double) count; - } - - return retval; -} - -DEFUN (fwrite, args, , +DEFUN (fwrite, , , "COUNT = fwrite (FILENUM, DATA, PRECISION)\n\ \n\ Writes data to a file in binary form of size PRECISION\n\ @@ -1820,39 +695,8 @@ \n\ COUNT : number of elements written") { - Octave_object retval; - - int nargin = args.length (); - - if (nargin < 2 || nargin > 3) - print_usage ("fwrite"); - else - retval = fwrite_internal (args); - - return retval; -} - -// Check for an EOF condition on a file opened by fopen. -// -// eof = feof (fid) -// -// fid : file id from fopen -// eof : non zero for an end of file condition - -static Octave_object -feof_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); - - retval(0) = (double) feof (file.fptr ()); - + octave_value_list retval; + // XXX IMPLEMENTME XXX return retval; } @@ -1862,125 +706,65 @@ Returns a non zero value for an end of file condition for the\n\ file specified by FILENAME or FILENUM from fopen") { - Octave_object retval; + double retval = -1.0; int nargin = args.length (); - if (nargin != 1) - print_usage ("feof"); - else - retval = feof_internal (args); - - return retval; -} - -// Check for an error condition on a file opened by fopen. -// -// [message, errnum] = ferror (fid) -// -// fid : file id from fopen -// message : system error message -// errnum : error number - -static Octave_object -ferror_internal (const Octave_object& args, int nargout) -{ - Octave_object retval; - - Pix p = return_valid_file (args(0)); - - if (! p) - return retval; + if (nargin == 1) + { + octave_stream *os = octave_stream_list::lookup (args(0)); - file_info file = file_list (p); - - int ierr = ferror (file.fptr ()); - - if (nargout > 1) - retval(1) = (double) ierr; - - retval(0) = strerror (ierr); - - return retval; -} - -DEFUN (ferror, args, nargout, - "ERROR = ferror (FILENAME or FILENUM)\n\ -\n\ - Returns a non zero value for an error condition on the\n\ - file specified by FILENAME or FILENUM from fopen") -{ - Octave_object retval; - - int nargin = args.length (); - - if (nargin != 1) - print_usage ("ferror"); + if (os) + retval = os->eof () ? 1.0 : 0.0; + else + gripe_invalid_file_id ("feof"); + } else - retval = ferror_internal (args, nargout); + print_usage ("feof"); return retval; } -static Octave_object -popen_internal (const Octave_object& args) +DEFUN (ferror, args, , + "ERROR = ferror (FILENAME or FILENUM, [\"clear\"])\n\ +\n\ + Returns a non zero value for an error condition on the\n\ + file specified by FILENAME or FILENUM from fopen") { - Octave_object retval; - - if (! args(0).is_string ()) - { - error ("popen: file name must be a string"); - return retval; - } - - Pix p = return_valid_file (args(0)); + octave_value_list retval; - if (p) - { - file_info file = file_list (p); - - retval(0) = (double) file.number (); + int nargin = args.length (); - return retval; - } + if (nargin == 1 || nargin == 2) + { + octave_stream *os = octave_stream_list::lookup (args(0)); - if (! args(1).is_string ()) - { - error ("popen: file mode must be a string"); - return retval; - } + if (os) + { + bool clear = false; - string name = args(0).string_value (); - string mode = args(1).string_value (); + if (nargin == 2) + { + string opt = args(1).string_value (); + + if (! error_state) + clear = (opt == "clear"); + else + return retval; + } - if (mode.length () > 1 || (mode[0] != 'w' && mode[0] != 'r')) - { - error ("popen: invalid mode, must be either \"r\" or \"w\"."); - return retval; - } + int error_number = 0; + + string error_message = os->error (clear, error_number); - file_stat fs (name); - - if (fs && fs.is_dir ()) - { - error ("popen: can't open directory"); - return retval; + retval(1) = (double) error_number; + retval(0) = error_message; + } + else + gripe_invalid_file_id ("ferror"); } - - FILE *file_ptr = popen (name.c_str (), mode.c_str ()); - - if (! file_ptr) - { - error ("popen: unable to start process `%s'", name.c_str ()); - return retval; - } - - int number = get_next_avail_file_num (); - - file_info file (number, name, file_ptr, mode); - file_list.append (file); - - retval(0) = (double) number; + else + print_usage ("ferror"); return retval; } @@ -1993,47 +777,43 @@ \"r\" : connect stdout of process to pipe\n\ \"w\" : connect stdin of process to pipe") { - Octave_object retval; + double retval = -1.0; int nargin = args.length (); - if (nargin != 2) - print_usage ("popen"); - else - retval = popen_internal (args); - - return retval; -} + if (nargin == 2) + { + string name = args(0).string_value (); -static Octave_object -pclose_internal (const Octave_object& args) -{ - Octave_object retval; + if (! error_state) + { + string mode = args(1).string_value (); - Pix p = return_valid_file (args(0)); - - if (! p) - return retval; + if (! error_state) + { + if (mode == "r") + { + octave_iprocstream *ips = new octave_iprocstream (name); - file_info file = file_list (p); - - if (file.number () < 3) - { - warning ("pclose: can't close stdin, stdout, or stderr!"); - return retval; - } + retval = octave_stream_list::insert (ips); + } + else if (mode == "w") + { + octave_oprocstream *ops = new octave_oprocstream (name); - int success = pclose (file.fptr ()); - next_available_file_number.push (file.number ()); - file_list.del (p); - - if (success == 0) - retval(0) = 1.0; // succeeded + retval = octave_stream_list::insert (ops); + } + else + ::error ("popen: invalid mode specified"); + } + else + ::error ("popen: mode must be a string"); + } + else + ::error ("popen: name must be a string"); + } else - { - error ("pclose: error on closing file"); - retval(0) = 0.0; // failed - } + print_usage ("popen"); return retval; } @@ -2043,471 +823,19 @@ \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) -{ - 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; - } - - string 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.c_str (), name.c_str (), 0) == -1) - error ("execute: unable to start process `%s'", name.c_str ()); - - 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 = get_next_avail_file_num (); - 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, args, , - "[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); - - 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; - } - - string name = args(0).string_value (); - - retval (0) = (double) system (name.c_str ()); - return retval; -} - -DEFUN (sync_system, args, , - "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; - } - - string 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.c_str ()); - exit (0); - retval (0) = 0.0; - return retval; - } - else - { - retval (0) = (double) pid; - return retval; - } -} - -DEFUN (async_system, args, , - "PID = async_system (FILENAME)\n\ -\n\ - Create a new process and start FILENAME") -{ - Octave_object retval; + double retval = -1.0; 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 (nargin == 1) { - 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, args, , - "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; - } - - string 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) oct_mkfifo (name, mode); - - return retval; -} + retval = (double) octave_stream_list::remove (args(0)); -DEFUN (mkfifo, args, , - "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; - } - - string name = args(0).string_value (); - - retval (0) = (double) oct_unlink (name); - - return retval; -} - -DEFUN (unlink, args, , - "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; -} - -static Octave_map -mk_stat_map (const file_stat& fs) -{ - Octave_map m; - - m["dev"] = (double) fs.dev (); - m["ino"] = (double) fs.ino (); - m["modestr"] = fs.mode_as_string (); - m["nlink"] = (double) fs.nlink (); - m["uid"] = (double) fs.uid (); - m["gid"] = (double) fs.gid (); -#if defined (HAVE_ST_RDEV) - m["rdev"] = (double) fs.rdev (); -#endif - m["size"] = (double) fs.size (); - m["atime"] = (double) fs.atime (); - m["mtime"] = (double) fs.mtime (); - m["ctime"] = (double) fs.ctime (); -#if defined (HAVE_ST_BLKSIZE) - m["blksize"] = (double) fs.blksize (); -#endif -#if defined (HAVE_ST_BLOCKS) - m["blocks"] = (double) fs.blocks (); -#endif - - return m; -} - -DEFUN (stat, args, , - "stat (NAME)\n\ -\n\ - Given the name of a file, return a structure with the following - elements:\n\ -\n\ - dev : id of device containing a directory entry for this file\n\ - ino : file number of the file\n\ - modestr : file mode, as a string of ten letters or dashes as in ls -l\n\ - nlink : number of links\n\ - uid : user id of file's owner\n\ - gid : group id of file's group \n\ - rdev : id of device for block or character special files\n\ - size : size in bytes\n\ - atime : time of last access\n\ - mtime : time of last modification\n\ - ctime : time of last file status change\n\ - blksize : size of blocks in the file\n\ - blocks : number of blocks allocated for file\n\ -\n\ - If the file does not exist, -1 is returned.") -{ - Octave_object retval; - - if (args.length () == 1) - { - string fname = oct_tilde_expand (args(0).string_value ()); - - if (! error_state) - { - file_stat fs (fname); - - if (fs) - retval = tree_constant (mk_stat_map (fs)); - else - retval = -1.0; - } + if (retval < 0) + gripe_invalid_file_id ("pclose"); } else - print_usage ("stat"); - - return retval; -} - -DEFUN (lstat, args, , - "lstat (NAME)\n\ -\n\ - Like stat (NAME), but if NAME refers to a symbolic link, returns\n\ - information about the link itself, not the file that it points to.") -{ - Octave_object retval; - - if (args.length () == 1) - { - string fname = oct_tilde_expand (args(0).string_value ()); - - if (! error_state) - { - file_stat fs (fname); - - if (fs) - retval = tree_constant (mk_stat_map (fs)); - else - retval = -1.0; - } - } - else - print_usage ("stat"); + print_usage ("pclose"); return retval; } @@ -2515,7 +843,7 @@ DEFUN (octave_tmp_file_name, args, , "octave_tmp_file_name ()") { - tree_constant retval; + octave_value retval; if (args.length () == 0) retval = oct_tempnam (); @@ -2533,7 +861,7 @@ int tmp = x % obase; if (tmp > ibase - 1) - error ("umask: invalid digit"); + ::error ("umask: invalid digit"); else { retval = tmp; @@ -2543,7 +871,7 @@ tmp = x % obase; if (tmp > ibase - 1) { - error ("umask: invalid digit"); + ::error ("umask: invalid digit"); break; } retval += mult * tmp; @@ -2563,7 +891,7 @@ be interpreted as an octal number); otherwise an error message is printed.") { - Octave_object retval; + octave_value_list retval; int status = 0; @@ -2574,7 +902,7 @@ if (error_state) { status = -1; - error ("umask: expecting integer argument"); + ::error ("umask: expecting integer argument"); } else { @@ -2583,7 +911,7 @@ if ((double) mask != dmask || mask < 0) { status = -1; - error ("umask: MASK must be a positive integer value"); + ::error ("umask: MASK must be a positive integer value"); } else { diff --git a/src/fsolve.cc b/src/fsolve.cc --- a/src/fsolve.cc +++ b/src/fsolve.cc @@ -26,7 +26,7 @@ #include -#include +#include #include "NLEqn.h" @@ -208,36 +208,33 @@ }; static void -print_fsolve_option_list (void) +print_fsolve_option_list (ostream& os) { - ostrstream output_buf; - print_usage ("fsolve_options", 1); - output_buf << "\n" - << "Options for fsolve include:\n\n" - << " keyword value\n" - << " ------- -----\n\n"; + os << "\n" + << "Options for fsolve include:\n\n" + << " keyword value\n" + << " ------- -----\n\n"; NLEQN_OPTIONS *list = fsolve_option_table; const char *keyword; while ((keyword = list->keyword) != 0) { - output_buf.form (" %-40s ", keyword); + os.form (" %-40s ", keyword); double val = (fsolve_opts.*list->d_get_fcn) (); if (val < 0.0) - output_buf << "computed automatically"; + os << "computed automatically"; else - output_buf << val; + os << val; - output_buf << "\n"; + os << "\n"; list++; } - output_buf << "\n" << ends; - maybe_page_output (output_buf); + os << "\n"; } static void @@ -294,7 +291,7 @@ if (nargin == 0) { - print_fsolve_option_list (); + print_fsolve_option_list (octave_stdout); return retval; } else if (nargin == 1 || nargin == 2) diff --git a/src/help.cc b/src/help.cc --- a/src/help.cc +++ b/src/help.cc @@ -315,19 +315,17 @@ Use the command `help -i ' to search the manual index.\n" static void -additional_help_message (ostrstream& output_buf) +additional_help_message (ostream& os) { #ifdef USE_GNU_INFO if (! user_pref.suppress_verbose_help_message) - output_buf << VERBOSE_HELP_MESSAGE; + os << VERBOSE_HELP_MESSAGE; #endif } void print_usage (const string& nm, int just_usage) { - ostrstream output_buf; - symbol_record *sym_rec = global_sym_tab->lookup (nm, 0, 0); if (sym_rec) { @@ -335,13 +333,11 @@ if (h.length () > 0) { - output_buf << "\n*** " << nm << ":\n\n" + octave_stdout << "\n*** " << nm << ":\n\n" << h << "\n"; if (! just_usage) - additional_help_message (output_buf); - output_buf << ends; - maybe_page_output (output_buf); + additional_help_message (octave_stdout); } } else @@ -349,20 +345,20 @@ } static void -display_names_from_help_list (ostrstream& output_buf, help_list *list, +display_names_from_help_list (ostream& os, help_list *list, const char *desc) { int count = 0; string_vector symbols = names (list, count); if (! symbols.empty ()) { - output_buf << "\n*** " << desc << ":\n\n"; - symbols.list_in_columns (output_buf); + os << "\n*** " << desc << ":\n\n"; + symbols.list_in_columns (os); } } static string -print_symbol_type (ostrstream& output_buf, symbol_record *sym_rec, +print_symbol_type (ostream& os, symbol_record *sym_rec, const string& name, int print) { string retval; @@ -380,16 +376,16 @@ ff = ff.length () > 0 ? ff : fn; if (print) - output_buf << name - << " is the function defined from:\n" - << ff << "\n"; + os << name + << " is the function defined from:\n" + << ff << "\n"; else retval = ff; } else { if (print) - output_buf << name << " is a user-defined function\n"; + os << name << " is a user-defined function\n"; else retval = "user-defined function"; } @@ -397,36 +393,35 @@ else if (sym_rec->is_text_function ()) { if (print) - output_buf << name << " is a builtin text-function\n"; + os << name << " is a builtin text-function\n"; else retval = "builtin text-function"; } else if (sym_rec->is_builtin_function ()) { if (print) - output_buf << name << " is a builtin function\n"; + os << name << " is a builtin function\n"; else retval = "builtin function"; } else if (sym_rec->is_user_variable ()) { if (print) - output_buf << name << " is a user-defined variable\n"; + os << name << " is a user-defined variable\n"; else retval = "user-defined variable"; } else if (sym_rec->is_builtin_variable ()) { if (print) - output_buf << name << " is a builtin variable\n"; + os << name << " is a builtin variable\n"; else retval = "builtin variable"; } else { if (print) - output_buf << "which: `" << name - << "' has unknown type\n"; + os << "which: `" << name << "' has unknown type\n"; else retval = "unknown type"; } @@ -435,25 +430,23 @@ } static void -display_symtab_names (ostrstream& output_buf, const string_vector& names, +display_symtab_names (ostream& os, const string_vector& names, int /* count */, const string& desc) { if (! names.empty ()) { - output_buf << "\n*** " << desc << ":\n\n"; - names.list_in_columns (output_buf); + os << "\n*** " << desc << ":\n\n"; + names.list_in_columns (os); } } static void simple_help (void) { - ostrstream output_buf; - - display_names_from_help_list (output_buf, operator_help (), + display_names_from_help_list (octave_stdout, operator_help (), "operators"); - display_names_from_help_list (output_buf, keyword_help (), + display_names_from_help_list (octave_stdout, keyword_help (), "reserved words"); #ifdef LIST_SYMBOLS @@ -464,7 +457,7 @@ { \ int count; \ string_vector names = global_sym_tab->list (count, 0, 0, 1, type); \ - display_symtab_names (output_buf, names, count, msg); \ + display_symtab_names (octave_stdout, names, count, msg); \ } \ while (0) @@ -496,17 +489,16 @@ if (! names.empty ()) { - output_buf << "\n*** function files in " - << make_absolute (dirs[i], the_current_working_directory) - << ":\n\n"; + octave_stdout << "\n*** function files in " + << make_absolute (dirs[i], + the_current_working_directory) + << ":\n\n"; - names.list_in_columns (output_buf); + names.list_in_columns (octave_stdout); } } - additional_help_message (output_buf); - output_buf << ends; - maybe_page_output (output_buf); + additional_help_message (octave_stdout); } #ifdef USE_GNU_INFO @@ -591,7 +583,7 @@ } int -help_from_list (ostrstream& output_buf, const help_list *list, +help_from_list (ostream& os, const help_list *list, const string& nm, int usage) { char *name; @@ -600,13 +592,13 @@ if (strcmp (name, nm.c_str ()) == 0) { if (usage) - output_buf << "\nusage: "; + os << "\nusage: "; else { - output_buf << "\n*** " << nm << ":\n\n"; + os << "\n*** " << nm << ":\n\n"; } - output_buf << list->help << "\n"; + os << list->help << "\n"; return 1; } @@ -618,17 +610,15 @@ static void builtin_help (int argc, const string_vector& argv) { - ostrstream output_buf; - help_list *op_help_list = operator_help (); help_list *kw_help_list = keyword_help (); for (int i = 1; i < argc; i++) { - if (help_from_list (output_buf, op_help_list, argv[i], 0)) + if (help_from_list (octave_stdout, op_help_list, argv[i], 0)) continue; - if (help_from_list (output_buf, kw_help_list, argv[i], 0)) + if (help_from_list (octave_stdout, kw_help_list, argv[i], 0)) continue; symbol_record *sym_rec = lookup_by_name (argv[i], 0); @@ -639,8 +629,8 @@ if (h.length () > 0) { - print_symbol_type (output_buf, sym_rec, argv[i], 1); - output_buf << "\n" << h << "\n"; + print_symbol_type (octave_stdout, sym_rec, argv[i], 1); + octave_stdout << "\n" << h << "\n"; continue; } } @@ -651,18 +641,17 @@ if (! h.empty ()) { - output_buf << argv[i] << " is the file:\n" + octave_stdout << argv[i] << " is the file:\n" << path << "\n\n" << h << "\n"; continue; } - output_buf << "\nhelp: sorry, `" << argv[i] << "' is not documented\n"; + octave_stdout << "\nhelp: sorry, `" << argv[i] + << "' is not documented\n"; } - additional_help_message (output_buf); - output_buf << ends; - maybe_page_output (output_buf); + additional_help_message (octave_stdout); } #ifdef USE_GNU_INFO @@ -834,14 +823,14 @@ output_buf << ends; + char *s = output_buf.str (); + if (nargout == 0) - maybe_page_output (output_buf); + octave_stdout << s; else - { - char *s = output_buf.str (); - retval = s; - delete [] s; - } + retval = s; + + delete [] s; } else print_usage ("type"); @@ -871,8 +860,6 @@ if (nargout > 0) retval.resize (argc-1, Matrix ()); - ostrstream output_buf; - for (int i = 1; i < argc; i++) { symbol_record *sym_rec = lookup_by_name (argv[i], 0); @@ -880,7 +867,7 @@ if (sym_rec) { int print = (nargout == 0); - string tmp = print_symbol_type (output_buf, sym_rec, + string tmp = print_symbol_type (octave_stdout, sym_rec, argv[i], print); if (! print) retval(i) = tmp; @@ -888,13 +875,11 @@ else { if (nargout == 0) - output_buf << "which: `" << argv[i] << "' is undefined\n"; + octave_stdout << "which: `" << argv[i] << "' is undefined\n"; else retval(i) = "undefined"; } } - output_buf << ends; - maybe_page_output (output_buf); } else print_usage ("which"); diff --git a/src/input.cc b/src/input.cc --- a/src/input.cc +++ b/src/input.cc @@ -46,7 +46,6 @@ #include #include -#include #ifdef HAVE_UNISTD_H #include @@ -369,27 +368,23 @@ if (do_echo) { - ostrstream buf; - if (forced_interactive) { if (promptflag > 0) - buf << decode_prompt_string (user_pref.ps1); + octave_stdout << decode_prompt_string (user_pref.ps1); else - buf << decode_prompt_string (user_pref.ps2); + octave_stdout << decode_prompt_string (user_pref.ps2); } else - buf << decode_prompt_string (user_pref.ps4); + octave_stdout << decode_prompt_string (user_pref.ps4); if (! input_string.empty ()) { - buf << input_string; + octave_stdout << input_string; if (input_string[input_string.length () - 1] != '\n') - buf << "\n"; + octave_stdout << "\n"; } - - maybe_page_output (buf); } } @@ -478,10 +473,10 @@ if (interactive) { pipe_handler_error_count = 0; - flush_output_to_pager (); + flush_octave_stdout (); } - maybe_write_to_diary_file (prompt); + octave_diary << prompt; retval = gnu_readline (prompt.c_str ()); } @@ -498,12 +493,12 @@ if (! input_from_startup_file) octave_command_history.add (current_input_line); - maybe_write_to_diary_file (current_input_line); + octave_diary << current_input_line; do_input_echo (current_input_line); } - maybe_write_to_diary_file ("\n"); + octave_diary << "\n"; return retval; } @@ -1030,7 +1025,7 @@ again: - flush_output_to_pager (); + flush_octave_stdout (); char *input_buf = gnu_readline (prompt.c_str ()); diff --git a/src/load-save.cc b/src/load-save.cc --- a/src/load-save.cc +++ b/src/load-save.cc @@ -1350,15 +1350,16 @@ if (list_only && count) { + output_buf << ends; + + char *msg = output_buf.str (); + if (nargout > 0) - { - output_buf << ends; - char *msg = output_buf.str (); - retval = msg; - delete [] msg; - } + retval = msg; else - maybe_page_output (output_buf); + octave_stdout << msg; + + delete [] msg; } return retval; @@ -2117,14 +2118,15 @@ } static void -write_binary_header (ostream& stream, load_save_format format) +write_binary_header (ostream& os, load_save_format format) { if (format == LS_BINARY) { - stream << (octave_words_big_endian ? "Octave-1-B" : "Octave-1-L"); + os << (octave_words_big_endian ? "Octave-1-B" : "Octave-1-L"); char tmp = (char) native_float_format; - stream.write (&tmp, 1); + + os.write (&tmp, 1); } } @@ -2248,12 +2250,8 @@ // XXX FIXME XXX -- should things intended for the screen end up // in a octave_value (string)? - ostrstream buf; - - save_vars (argv, i, argc, buf, save_builtins, format, + save_vars (argv, i, argc, octave_stdout, save_builtins, format, save_as_floats); - - maybe_page_output (buf); } // Guard against things like `save a*', which are probably mistakes... diff --git a/src/lsode.cc b/src/lsode.cc --- a/src/lsode.cc +++ b/src/lsode.cc @@ -26,7 +26,7 @@ #include -#include +#include #include "LSODE.h" @@ -223,36 +223,33 @@ }; static void -print_lsode_option_list (void) +print_lsode_option_list (ostream& os) { - ostrstream output_buf; - print_usage ("lsode_options", 1); - output_buf << "\n" - << "Options for lsode include:\n\n" - << " keyword value\n" - << " ------- -----\n\n"; + os << "\n" + << "Options for lsode include:\n\n" + << " keyword value\n" + << " ------- -----\n\n"; LSODE_OPTIONS *list = lsode_option_table; const char *keyword; while ((keyword = list->keyword) != 0) { - output_buf.form (" %-40s ", keyword); + os.form (" %-40s ", keyword); double val = (lsode_opts.*list->d_get_fcn) (); if (val < 0.0) - output_buf << "computed automatically"; + os << "computed automatically"; else - output_buf << val; + os << val; - output_buf << "\n"; + os << "\n"; list++; } - output_buf << "\n" << ends; - maybe_page_output (output_buf); + os << "\n"; } static void @@ -309,7 +306,7 @@ if (nargin == 0) { - print_lsode_option_list (); + print_lsode_option_list (octave_stdout); return retval; } else if (nargin == 1 || nargin == 2) diff --git a/src/npsol.cc b/src/npsol.cc --- a/src/npsol.cc +++ b/src/npsol.cc @@ -26,7 +26,7 @@ #include -#include +#include #include "NPSOL.h" @@ -673,45 +673,42 @@ }; static void -print_npsol_option_list (void) +print_npsol_option_list (ostream& os) { - ostrstream output_buf; - print_usage ("npsol_options", 1); - output_buf << "\n" - << "Options for npsol include:\n\n" - << " keyword value\n" - << " ------- -----\n\n"; + os << "\n" + << "Options for npsol include:\n\n" + << " keyword value\n" + << " ------- -----\n\n"; NPSOL_OPTIONS *list = npsol_option_table; const char *keyword; while ((keyword = list->keyword) != 0) { - output_buf.form (" %-40s ", keyword); + os.form (" %-40s ", keyword); if (list->d_get_fcn) { double val = (npsol_opts.*list->d_get_fcn) (); if (val < 0.0) - output_buf << "computed automatically"; + os << "computed automatically"; else - output_buf << val; + os << val; } else { int val = (npsol_opts.*list->i_get_fcn) (); if (val < 0) - output_buf << "depends on problem size"; + os << "depends on problem size"; else - output_buf << val; + os << val; } - output_buf << "\n"; + os << "\n"; list++; } - output_buf << "\n" << ends; - maybe_page_output (output_buf); + os << "\n"; } static void @@ -796,7 +793,7 @@ if (nargin == 0) { - print_npsol_option_list (); + print_npsol_option_list (octave_stdout); return retval; } else if (nargin == 1 || nargin == 2) diff --git a/src/oct-hist.cc b/src/oct-hist.cc --- a/src/oct-hist.cc +++ b/src/oct-hist.cc @@ -38,7 +38,6 @@ #include #include -#include #ifdef HAVE_UNISTD_H #include @@ -196,17 +195,8 @@ int len = hlist.length (); - if (len > 0) - { - ostrstream output_buf; - - for (i = 0; i < len; i++) - output_buf << hlist[i] << "\n"; - - output_buf << ends; - - maybe_page_output (output_buf); - } + for (i = 0; i < len; i++) + octave_stdout << hlist[i] << "\n"; } // Read the edited history lines from STREAM and return them diff --git a/src/octave.cc b/src/octave.cc --- a/src/octave.cc +++ b/src/octave.cc @@ -58,7 +58,6 @@ #include "lex.h" #include "oct-hist.h" #include "toplev.h" -#include "pager.h" #include "parse.h" #include "pathsearch.h" #include "procstream.h" @@ -398,8 +397,6 @@ init_user_prefs (); - initialize_pager (); - sysdep_init (); initialize_error_handlers (); diff --git a/src/pager.h b/src/pager.h --- a/src/pager.h +++ b/src/pager.h @@ -23,17 +23,98 @@ #if !defined (octave_pager_h) #define octave_pager_h 1 -class ostrstream; - #include -extern char *get_pager (void); -extern void initialize_pager (void); -extern void maybe_page_output (ostrstream& msg_buf); -extern void flush_output_to_pager (void); +#include +#include + +#ifdef HAVE_SYS_TYPES_H +#include +#endif + +class +octave_pager_buf : public strstreambuf +{ +public: + + octave_pager_buf (int size = 0) : strstreambuf (size) { } + +protected: + + int sync (void); +}; + +class +octave_pager_stream : public ostream +{ +protected: + + octave_pager_stream (void); + +public: + + ~octave_pager_stream (void); + + static octave_pager_stream& stream (void); + +private: + + static octave_pager_stream *instance; + + octave_pager_buf *pb; + + // No copying! + + octave_pager_stream (const octave_pager_stream&); + + octave_pager_stream& operator = (const octave_pager_stream&); +}; -extern void close_diary_file (void); -extern void maybe_write_to_diary_file (const string& s); +class +octave_diary_buf : public strstreambuf +{ +public: + + octave_diary_buf (int size = 0) : strstreambuf (size) { } + +protected: + + int sync (void); +}; + +class +octave_diary_stream : public ostream +{ +protected: + + octave_diary_stream (void); + +public: + + ~octave_diary_stream (void); + + static octave_diary_stream& stream (void); + +private: + + static octave_diary_stream *instance; + + octave_diary_buf *db; + + // No copying! + + octave_diary_stream (const octave_diary_stream&); + + octave_diary_stream& operator = (const octave_diary_stream&); +}; + +#define octave_stdout (octave_pager_stream::stream ()) + +#define octave_diary (octave_diary_stream::stream ()) + +extern void flush_octave_stdout (void); + +extern pid_t octave_pager_pid; #endif diff --git a/src/procstream.h b/src/procstream.h --- a/src/procstream.h +++ b/src/procstream.h @@ -28,7 +28,12 @@ #endif #include -#include + +#ifdef HAVE_SYS_TYPES_H +#include +#endif + +#include "oct-procbuf.h" class procstreambase : virtual public ios @@ -47,9 +52,11 @@ int close (void); + pid_t pid (void) { return pb.pid (); } + private: - procbuf pb; + octave_procbuf pb; void pb_init (void) { init (&pb); } diff --git a/src/pt-const.cc b/src/pt-const.cc --- a/src/pt-const.cc +++ b/src/pt-const.cc @@ -35,7 +35,6 @@ #include #include -#include #include @@ -252,24 +251,18 @@ void octave_value::print (void) { - ostrstream output_buf; - print (output_buf); - output_buf << ends; - maybe_page_output (output_buf); + print (octave_stdout); } void octave_value::print_with_name (const string& name, bool print_padding) { - ostrstream output_buf; - print_with_name (output_buf, name, print_padding); - output_buf << ends; - maybe_page_output (output_buf); + print_with_name (octave_stdout, name, print_padding); } void octave_value::print_with_name (ostream& output_buf, const string& name, - bool print_padding) + bool print_padding) { bool pad_after = false; diff --git a/src/pt-fcn.cc b/src/pt-fcn.cc --- a/src/pt-fcn.cc +++ b/src/pt-fcn.cc @@ -29,7 +29,6 @@ #endif #include -#include #include "defun.h" #include "error.h" @@ -416,10 +415,7 @@ void tree_function::print_code_function_header (void) { - ostrstream output_buf; - print_code_function_header (output_buf); - output_buf << ends; - maybe_page_output (output_buf); + print_code_function_header (octave_stdout); } void @@ -470,10 +466,7 @@ void tree_function::print_code_function_trailer (void) { - ostrstream output_buf; - print_code_function_trailer (output_buf); - output_buf << ends; - maybe_page_output (output_buf); + print_code_function_trailer (octave_stdout); } void diff --git a/src/pt-misc.cc b/src/pt-misc.cc --- a/src/pt-misc.cc +++ b/src/pt-misc.cc @@ -29,7 +29,6 @@ #endif #include -#include #ifdef HAVE_UNISTD_H #include @@ -85,12 +84,7 @@ { if (in_function_body && (user_pref.echo_executing_commands & ECHO_FUNCTIONS)) - { - ostrstream output_buf; - print_code (output_buf); - output_buf << ends; - maybe_page_output (output_buf); - } + print_code (octave_stdout); } void diff --git a/src/pt-mvr.cc b/src/pt-mvr.cc --- a/src/pt-mvr.cc +++ b/src/pt-mvr.cc @@ -29,7 +29,6 @@ #endif #include -#include #include "error.h" #include "oct-obj.h" @@ -342,11 +341,7 @@ break; if (print && pad_after) - { - ostrstream output_buf; - output_buf << "\n" << ends; - maybe_page_output (output_buf); - } + octave_stdout << "\n"; if (print) results(i).print_with_name (lhs_expr->name (), 0); @@ -365,11 +360,7 @@ } if (print && pad_after) - { - ostrstream output_buf; - output_buf << "\n" << ends; - maybe_page_output (output_buf); - } + octave_stdout << "\n"; } return results; diff --git a/src/qpsol.cc b/src/qpsol.cc --- a/src/qpsol.cc +++ b/src/qpsol.cc @@ -26,7 +26,7 @@ #include -#include +#include #include "QPSOL.h" @@ -314,45 +314,42 @@ }; static void -print_qpsol_option_list (void) +print_qpsol_option_list (ostream& os) { - ostrstream output_buf; - print_usage ("qpsol_options", 1); - output_buf << "\n" - << "Options for qpsol include:\n\n" - << " keyword value\n" - << " ------- -----\n\n"; + os << "\n" + << "Options for qpsol include:\n\n" + << " keyword value\n" + << " ------- -----\n\n"; QPSOL_OPTIONS *list = qpsol_option_table; const char *keyword; while ((keyword = list->keyword) != 0) { - output_buf.form (" %-40s ", keyword); + os.form (" %-40s ", keyword); if (list->d_get_fcn) { double val = (qpsol_opts.*list->d_get_fcn) (); if (val < 0.0) - output_buf << "computed automatically"; + os << "computed automatically"; else - output_buf << val; + os << val; } else { int val = (qpsol_opts.*list->i_get_fcn) (); if (val < 0) - output_buf << "depends on problem size"; + os << "depends on problem size"; else - output_buf << val; + os << val; } - output_buf << "\n"; + os << "\n"; list++; } - output_buf << "\n" << ends; - maybe_page_output (output_buf); + os << "\n"; } static void @@ -437,7 +434,7 @@ if (nargin == 0) { - print_qpsol_option_list (); + print_qpsol_option_list (octave_stdout); return retval; } else if (nargin == 1 || nargin == 2) diff --git a/src/quad.cc b/src/quad.cc --- a/src/quad.cc +++ b/src/quad.cc @@ -26,7 +26,7 @@ #include -#include +#include #include "Quad.h" @@ -280,36 +280,33 @@ }; static void -print_quad_option_list (void) +print_quad_option_list (ostream& os) { - ostrstream output_buf; - print_usage ("quad_options", 1); - output_buf << "\n" - << "Options for quad include:\n\n" - << " keyword value\n" - << " ------- -----\n\n"; + os << "\n" + << "Options for quad include:\n\n" + << " keyword value\n" + << " ------- -----\n\n"; QUAD_OPTIONS *list = quad_option_table; const char *keyword; while ((keyword = list->keyword) != 0) { - output_buf.form (" %-40s ", keyword); + os.form (" %-40s ", keyword); double val = (quad_opts.*list->d_get_fcn) (); if (val < 0.0) - output_buf << "computed automatically"; + os << "computed automatically"; else - output_buf << val; + os << val; - output_buf << "\n"; + os << "\n"; list++; } - output_buf << "\n" << ends; - maybe_page_output (output_buf); + os << "\n"; } static void @@ -366,7 +363,7 @@ if (nargin == 0) { - print_quad_option_list (); + print_quad_option_list (octave_stdout); return retval; } else if (nargin == 1 || nargin == 2) diff --git a/src/syswait.h b/src/syswait.h --- a/src/syswait.h +++ b/src/syswait.h @@ -26,14 +26,22 @@ // This mess suggested by the autoconf manual. #include + #if HAVE_SYS_WAIT_H #include #endif + +#ifndef WIFEXITED +#define WIFEXITED(stat_val) (((stat_val) & 255) == 0) +#endif + #ifndef WEXITSTATUS #define WEXITSTATUS(stat_val) ((unsigned)(stat_val) >> 8) #endif -#ifndef WIFEXITED -#define WIFEXITED(stat_val) (((stat_val) & 255) == 0) + +#ifndef WIFSIGNALLED +#define WIFSIGNALLED(stat_val) \ + (((stat_val) & 0177) != 0177 && ((stat_val) & 0177) != 0) #endif #endif diff --git a/src/toplev.cc b/src/toplev.cc --- a/src/toplev.cc +++ b/src/toplev.cc @@ -308,8 +308,6 @@ close_plot_stream (); - close_diary_file (); - close_files (); cleanup_tmp_files (); @@ -362,25 +360,17 @@ if (nargin != 0) warning ("computer: ignoring extra arguments"); - ostrstream output_buf; + string msg; if (strcmp (TARGET_HOST_TYPE, "unknown") == 0) - output_buf << "Hi Dave, I'm a HAL-9000"; + msg = "Hi Dave, I'm a HAL-9000"; else - output_buf << TARGET_HOST_TYPE; + msg = TARGET_HOST_TYPE; if (nargout == 0) - { - output_buf << "\n" << ends; - maybe_page_output (output_buf); - } + octave_stdout << msg << "\n"; else - { - output_buf << ends; - char *msg = output_buf.str (); - retval = msg; - delete [] msg; - } + retval = msg; return retval; } @@ -420,8 +410,7 @@ { octave_value_list retval; - ostrstream output_buf; - output_buf << "\n" OCTAVE_NAME_VERSION_AND_COPYRIGHT "\n\n\ + octave_stdout << "\n" OCTAVE_NAME_VERSION_AND_COPYRIGHT "\n\n\ This program is free software; you can redistribute it and/or modify\n\ it under the terms of the GNU General Public License as published by\n\ the Free Software Foundation; either version 2 of the License, or\n\ @@ -437,9 +426,6 @@ Foundation, 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.\n\ \n"; - output_buf << ends; - maybe_page_output (output_buf); - return retval; } @@ -627,18 +613,19 @@ if (cmd && *cmd) { ostrstream output_buf; - + char ch; while (cmd->get (ch)) { - if (return_output || user_pref.page_screen_output) + if (return_output) output_buf.put (ch); + + if (user_pref.page_screen_output) + octave_stdout.put (ch); else cout.put (ch); } - output_buf << ends; - status = cmd->close (); // The value in status is as returned by waitpid. If the @@ -657,8 +644,6 @@ delete [] msg; } - else - maybe_page_output (output_buf); } else error ("unable to start subprocess for `%s'", cmd_str.c_str ()); diff --git a/src/variables.cc b/src/variables.cc --- a/src/variables.cc +++ b/src/variables.cc @@ -30,6 +30,7 @@ #include +#include #include #ifdef HAVE_UNISTD_H @@ -1122,26 +1123,26 @@ // List variable names. static void -print_symbol_info_line (ostrstream& output_buf, const symbol_record_info& s) +print_symbol_info_line (ostream& os, const symbol_record_info& s) { - output_buf << (s.is_read_only () ? " -" : " w"); - output_buf << (s.is_eternal () ? "- " : "d "); + os << (s.is_read_only () ? " -" : " w"); + os << (s.is_eternal () ? "- " : "d "); #if 0 - output_buf << (s.hides_fcn () ? "f" : (s.hides_builtin () ? "F" : "-")); + os << (s.hides_fcn () ? "f" : (s.hides_builtin () ? "F" : "-")); #endif - output_buf.form (" %-16s", s.type_as_string ().c_str ()); + os.form (" %-16s", s.type_as_string ().c_str ()); if (s.is_function ()) - output_buf << " - -"; + os << " - -"; else { - output_buf.form ("%7d", s.rows ()); - output_buf.form ("%7d", s.columns ()); + os.form ("%7d", s.rows ()); + os.form ("%7d", s.columns ()); } - output_buf << " " << s.name () << "\n"; + os << " " << s.name () << "\n"; } static void -print_long_listing (ostrstream& output_buf, symbol_record_info *s) +print_long_listing (ostream& os, symbol_record_info *s) { if (! s) return; @@ -1149,14 +1150,14 @@ symbol_record_info *ptr = s; while (ptr->is_defined ()) { - print_symbol_info_line (output_buf, *ptr); + print_symbol_info_line (os, *ptr); ptr++; } } static int maybe_list (const char *header, const string_vector& argv, int argc, - ostrstream& output_buf, int show_verbose, symbol_table + ostream& os, int show_verbose, symbol_table *sym_tab, unsigned type, unsigned scope) { int count; @@ -1167,11 +1168,11 @@ symbols = sym_tab->long_list (count, argv, argc, 1, type, scope); if (symbols && count > 0) { - output_buf << "\n" << header << "\n\n" + os << "\n" << header << "\n\n" << "prot type rows cols name\n" << "==== ==== ==== ==== ====\n"; - print_long_listing (output_buf, symbols); + print_long_listing (os, symbols); status = 1; } delete [] symbols; @@ -1182,8 +1183,8 @@ type, scope); if (symbols.length () > 0 && count > 0) { - output_buf << "\n" << header << "\n\n"; - symbols.list_in_columns (output_buf); + os << "\n" << header << "\n\n"; + symbols.list_in_columns (os); status = 1; } } @@ -1286,18 +1287,17 @@ show_variables = 1; } - ostrstream output_buf; int pad_after = 0; if (show_builtins) { pad_after += maybe_list ("*** built-in variables:", pats, npats, - output_buf, show_verbose, global_sym_tab, + octave_stdout, show_verbose, global_sym_tab, symbol_def::BUILTIN_VARIABLE, SYMTAB_ALL_SCOPES); pad_after += maybe_list ("*** built-in functions:", pats, npats, - output_buf, show_verbose, global_sym_tab, + octave_stdout, show_verbose, global_sym_tab, symbol_def::BUILTIN_FUNCTION, SYMTAB_ALL_SCOPES); } @@ -1305,7 +1305,7 @@ if (show_functions) { pad_after += maybe_list ("*** currently compiled functions:", - pats, npats, output_buf, show_verbose, + pats, npats, octave_stdout, show_verbose, global_sym_tab, symbol_def::USER_FUNCTION, SYMTAB_ALL_SCOPES); } @@ -1313,21 +1313,18 @@ if (show_variables) { pad_after += maybe_list ("*** local user variables:", pats, npats, - output_buf, show_verbose, curr_sym_tab, + octave_stdout, show_verbose, curr_sym_tab, symbol_def::USER_VARIABLE, SYMTAB_LOCAL_SCOPE); pad_after += maybe_list ("*** globally visible user variables:", - pats, npats, output_buf, show_verbose, + pats, npats, octave_stdout, show_verbose, curr_sym_tab, symbol_def::USER_VARIABLE, SYMTAB_GLOBAL_SCOPE); } if (pad_after) - output_buf << "\n"; - - output_buf << ends; - maybe_page_output (output_buf); + octave_stdout << "\n"; return retval; }