Mercurial > octave
changeset 25435:a52e6fb674b1
eliminate some singletons and static & global variables
* pager.h, pager.cc: Rewrite pager_stream and diary_stream classes so
they are not singletons. Change all uses.
(output_system): New class.
* interpreter.h, interpreter.cc (interpreter::m_output_system):
New data member. Provide access function.
* interpreter-private.h, interpreter-private.cc
(__get_output_system__): New function.
author | John W. Eaton <jwe@octave.org> |
---|---|
date | Fri, 25 May 2018 16:30:01 -0400 |
parents | 859ad1f0b85e |
children | 996d78102a71 |
files | libinterp/corefcn/input.cc libinterp/corefcn/interpreter-private.cc libinterp/corefcn/interpreter-private.h libinterp/corefcn/interpreter.cc libinterp/corefcn/interpreter.h libinterp/corefcn/oct-stream.cc libinterp/corefcn/pager.cc libinterp/corefcn/pager.h |
diffstat | 8 files changed, 571 insertions(+), 407 deletions(-) [+] |
line wrap: on
line diff
--- a/libinterp/corefcn/input.cc Sat Mar 17 11:59:05 2018 -0500 +++ b/libinterp/corefcn/input.cc Fri May 25 16:30:01 2018 -0400 @@ -629,10 +629,9 @@ std::string prompt = args(0).xstring_value ("input: unrecognized argument"); - octave::flush_stdout (); + output_system& output_sys = __get_output_system__ ("do_sync"); - octave::pager_stream::reset (); - octave::diary_stream::reset (); + output_sys.reset (); octave_diary << prompt; @@ -939,10 +938,9 @@ pipe_handler_error_count = 0; - flush_stdout (); + output_system& output_sys = __get_output_system__ ("do_sync"); - pager_stream::reset (); - diary_stream::reset (); + output_sys.reset (); octave_diary << prompt;
--- a/libinterp/corefcn/interpreter-private.cc Sat Mar 17 11:59:05 2018 -0500 +++ b/libinterp/corefcn/interpreter-private.cc Fri May 25 16:30:01 2018 -0400 @@ -37,6 +37,7 @@ #include "interpreter.h" #include "load-path.h" #include "ov-classdef.h" +#include "pager.h" #include "symtab.h" namespace octave @@ -75,6 +76,13 @@ return interp.get_input_system (); } + output_system& __get_output_system__ (const std::string& who) + { + interpreter& interp = __get_interpreter__ (who); + + return interp.get_output_system (); + } + load_path& __get_load_path__ (const std::string& who) { interpreter& interp = __get_interpreter__ (who);
--- a/libinterp/corefcn/interpreter-private.h Sat Mar 17 11:59:05 2018 -0500 +++ b/libinterp/corefcn/interpreter-private.h Fri May 25 16:30:01 2018 -0400 @@ -42,6 +42,7 @@ class input_system; class interpreter; class load_path; + class output_system; class tree_evaluator; class type_info; @@ -55,6 +56,8 @@ extern load_path& __get_load_path__ (const std::string& who); + extern output_system& __get_output_system__ (const std::string& who); + extern type_info& __get_type_info__ (const std::string& who); extern symbol_table& __get_symbol_table__ (const std::string& who);
--- a/libinterp/corefcn/interpreter.cc Sat Mar 17 11:59:05 2018 -0500 +++ b/libinterp/corefcn/interpreter.cc Fri May 25 16:30:01 2018 -0400 @@ -327,6 +327,7 @@ m_environment (), m_help_system (*this), m_input_system (*this), + m_output_system (*this), m_dynamic_loader (*this), m_load_path (), m_type_info (),
--- a/libinterp/corefcn/interpreter.h Sat Mar 17 11:59:05 2018 -0500 +++ b/libinterp/corefcn/interpreter.h Fri May 25 16:30:01 2018 -0400 @@ -40,6 +40,7 @@ #include "oct-stream.h" #include "ov-classdef.h" #include "ov-typeinfo.h" +#include "pager.h" #include "pt-eval.h" #include "symtab.h" #include "url-handle-manager.h" @@ -160,6 +161,11 @@ return m_input_system; } + output_system& get_output_system (void) + { + return m_output_system; + } + dynamic_loader& get_dynamic_loader (void) { return m_dynamic_loader; @@ -256,6 +262,8 @@ input_system m_input_system; + output_system m_output_system; + dynamic_loader m_dynamic_loader; load_path m_load_path;
--- a/libinterp/corefcn/oct-stream.cc Sat Mar 17 11:59:05 2018 -0500 +++ b/libinterp/corefcn/oct-stream.cc Fri May 25 16:30:01 2018 -0400 @@ -7282,7 +7282,7 @@ return retval; } - stream_list::stream_list (interpreter&) + stream_list::stream_list (interpreter& interp) : list (), lookup_cache (list.end ()), m_stdin_file (-1), m_stdout_file (-1), m_stderr_file (-1) { @@ -7293,7 +7293,10 @@ // FIXME: we should be accessing octave_stdout from the interpreter. - stream stdout_stream = octave_ostream::create (&octave_stdout, "stdout"); + output_system& output_sys = interp.get_output_system (); + + stream stdout_stream + = octave_ostream::create (&(output_sys.__stdout__ ()), "stdout"); stream stderr_stream = octave_ostream::create (&std::cerr, "stderr");
--- a/libinterp/corefcn/pager.cc Sat Mar 17 11:59:05 2018 -0500 +++ b/libinterp/corefcn/pager.cc Fri May 25 16:30:01 2018 -0400 @@ -32,13 +32,13 @@ #include "cmd-edit.h" #include "oct-env.h" #include "oct-syscalls.h" -#include "singleton-cleanup.h" #include "defaults.h" #include "defun.h" #include "error.h" #include "errwarn.h" #include "input.h" +#include "interpreter.h" #include "interpreter-private.h" #include "octave.h" #include "ovl.h" @@ -49,226 +49,93 @@ #include "utils.h" #include "variables.h" -// Our actual connection to the external pager. -static oprocstream *external_pager = nullptr; - -// TRUE means we write to the diary file. -static bool write_to_diary_file = false; - -// The name of the current diary file. -static std::string diary_file ("diary"); - -// The diary file. -static std::ofstream external_diary_file; - -static std::string -default_pager (void) -{ - std::string pager_binary = octave::sys::env::getenv ("PAGER"); - - if (pager_binary.empty ()) - pager_binary = octave::config::default_pager (); - - return pager_binary; -} - -// The shell command to run as the pager. -static std::string VPAGER = default_pager (); - -// The options to pass to the pager. -static std::string VPAGER_FLAGS; - -// TRUE means that if output is going to the pager, it is sent as soon -// as it is available. Otherwise, it is buffered and only sent to the -// pager when it is time to print another prompt. -static bool Vpage_output_immediately = false; - -// TRUE means all output intended for the screen should be passed -// through the pager. -static bool Vpage_screen_output = false; - -static bool really_flush_to_pager = false; - -static bool flushing_output_to_pager = false; - -static void -clear_external_pager (void) -{ - if (external_pager) - { - octave::child_list& kids - = octave::__get_child_list__ ("clear_external_pager"); - - kids.remove (external_pager->pid ()); - - delete external_pager; - external_pager = nullptr; - } -} - -static bool -pager_event_handler (pid_t pid, int status) -{ - bool retval = false; - - if (pid > 0) - { - if (octave::sys::wifexited (status) || octave::sys::wifsignaled (status)) - { - // Avoid warning() since that will put us back in the pager, - // which would be bad news. - - std::cerr << "warning: connection to external pager lost (pid = " - << pid << ')' << std::endl; - std::cerr << "warning: flushing pending output (please wait)" - << std::endl; - - // Request removal of this PID from the list of child - // processes. - - retval = true; - } - } - - return retval; -} - -static std::string -pager_command (void) -{ - std::string cmd = VPAGER; - - if (! (cmd.empty () || VPAGER_FLAGS.empty ())) - cmd += ' ' + VPAGER_FLAGS; - - return cmd; -} - -static void -do_sync (const char *msg, int len, bool bypass_pager) -{ - if (msg && len > 0) - { - if (bypass_pager) - { - std::cout.write (msg, len); - std::cout.flush (); - } - else - { - if (! external_pager) - { - std::string pgr = pager_command (); - - if (! pgr.empty ()) - { - external_pager = new oprocstream (pgr.c_str ()); - - if (external_pager) - { - octave::child_list& kids - = octave::__get_child_list__ ("do_sync"); - - kids.insert (external_pager->pid (), - pager_event_handler); - } - } - } - - if (external_pager) - { - if (external_pager->good ()) - { - external_pager->write (msg, len); - - external_pager->flush (); - -#if defined (EPIPE) - if (errno == EPIPE) - external_pager->setstate (std::ios::failbit); -#endif - } - else - { - // FIXME: omething is not right with the - // pager. If it died then we should receive a - // signal for that. If there is some other problem, - // then what? - } - } - else - { - std::cout.write (msg, len); - std::cout.flush (); - } - } - } -} - -// Assume our terminal wraps long lines. - -static bool -more_than_a_screenful (const char *s, int len) -{ - if (s) - { - int available_rows = octave::command_editor::terminal_rows () - 2; - - int cols = octave::command_editor::terminal_cols (); - - int count = 0; - - int chars_this_line = 0; - - for (int i = 0; i < len; i++) - { - if (*s++ == '\n') - { - count += chars_this_line / cols + 1; - chars_this_line = 0; - } - else - chars_this_line++; - } - - if (count > available_rows) - return true; - } - - return false; -} - namespace octave { + static bool + pager_event_handler (pid_t pid, int status) + { + bool retval = false; + + if (pid > 0) + { + if (octave::sys::wifexited (status) || octave::sys::wifsignaled (status)) + { + // Avoid warning() since that will put us back in the pager, + // which would be bad news. + + std::cerr << "warning: connection to external pager lost (pid = " + << pid << ')' << std::endl; + std::cerr << "warning: flushing pending output (please wait)" + << std::endl; + + // Request removal of this PID from the list of child + // processes. + + retval = true; + } + } + + return retval; + } + + // Assume our terminal wraps long lines. + + static bool + more_than_a_screenful (const char *s, int len) + { + if (s) + { + int available_rows = octave::command_editor::terminal_rows () - 2; + + int cols = octave::command_editor::terminal_cols (); + + int count = 0; + + int chars_this_line = 0; + + for (int i = 0; i < len; i++) + { + if (*s++ == '\n') + { + count += chars_this_line / cols + 1; + chars_this_line = 0; + } + else + chars_this_line++; + } + + if (count > available_rows) + return true; + } + + return false; + } + + static std::string default_pager (void) + { + std::string pager_binary = sys::env::getenv ("PAGER"); + + if (pager_binary.empty ()) + pager_binary = config::default_pager (); + + return pager_binary; + } + int pager_buf::sync (void) { - if (! application::interactive () - || application::forced_interactive () - || really_flush_to_pager - || (Vpage_screen_output && Vpage_output_immediately) - || ! Vpage_screen_output) - { - char *buf = eback (); + octave::output_system& output_sys + = octave::__get_output_system__ ("pager_buf::sync"); - int len = pptr () - buf; + char *buf = eback (); - bool bypass_pager = (! application::interactive () - || application::forced_interactive () - || ! Vpage_screen_output - || (really_flush_to_pager - && Vpage_screen_output - && ! Vpage_output_immediately - && ! more_than_a_screenful (buf, len))); + int len = pptr () - buf; - if (len > 0) - { - do_sync (buf, len, bypass_pager); + if (output_sys.sync (buf, len)) + { + flush_current_contents_to_diary (); - flush_current_contents_to_diary (); - - seekoff (0, std::ios::beg); - } + seekoff (0, std::ios::beg); } return 0; @@ -295,7 +162,11 @@ int diary_buf::sync (void) { - if (write_to_diary_file && external_diary_file) + output_system& output_sys = __get_output_system__ ("__stdout__"); + + std::ofstream& external_diary_file = output_sys.external_diary_file (); + + if (output_sys.write_to_diary_file () && external_diary_file) { char *buf = eback (); @@ -310,8 +181,6 @@ return 0; } - pager_stream *pager_stream::instance = nullptr; - pager_stream::pager_stream (void) : std::ostream (nullptr), pb (nullptr) { pb = new pager_buf (); @@ -325,24 +194,21 @@ delete pb; } - std::ostream& - pager_stream::stream (void) + std::ostream& pager_stream::stream (void) { - return instance_ok () ? *instance : std::cout; + return *this; } - void - pager_stream::flush_current_contents_to_diary (void) + void pager_stream::flush_current_contents_to_diary (void) { - if (instance_ok ()) - instance->do_flush_current_contents_to_diary (); + if (pb) + pb->flush_current_contents_to_diary (); } - void - pager_stream::set_diary_skip (void) + void pager_stream::set_diary_skip (void) { - if (instance_ok ()) - instance->do_set_diary_skip (); + if (pb) + pb->set_diary_skip (); } // Reinitialize the pager buffer to avoid hanging on to large internal @@ -350,29 +216,7 @@ // called when the pager is not in use. For example, just before // getting command-line input. - void - pager_stream::reset (void) - { - if (instance_ok ()) - instance->do_reset (); - } - - void - pager_stream::do_flush_current_contents_to_diary (void) - { - if (pb) - pb->flush_current_contents_to_diary (); - } - - void - pager_stream::do_set_diary_skip (void) - { - if (pb) - pb->set_diary_skip (); - } - - void - pager_stream::do_reset (void) + void pager_stream::reset (void) { delete pb; pb = new pager_buf (); @@ -380,27 +224,6 @@ setf (unitbuf); } - bool - pager_stream::instance_ok (void) - { - bool retval = true; - - if (! instance) - { - instance = new pager_stream (); - - if (instance) - singleton_cleanup_list::add (cleanup_instance); - } - - if (! instance) - error ("unable to create pager_stream object!"); - - return retval; - } - - diary_stream *diary_stream::instance = nullptr; - diary_stream::diary_stream (void) : std::ostream (nullptr), db (nullptr) { db = new diary_buf (); @@ -414,10 +237,9 @@ delete db; } - std::ostream& - diary_stream::stream (void) + std::ostream& diary_stream::stream (void) { - return instance_ok () ? *instance : std::cout; + return *this; } // Reinitialize the diary buffer to avoid hanging on to large internal @@ -425,15 +247,7 @@ // called when the pager is not in use. For example, just before // getting command-line input. - void - diary_stream::reset (void) - { - if (instance_ok ()) - instance->do_reset (); - } - - void - diary_stream::do_reset (void) + void diary_stream::reset (void) { delete db; db = new diary_buf (); @@ -441,82 +255,243 @@ setf (unitbuf); } - bool - diary_stream::instance_ok (void) + void flush_stdout (void) { - bool retval = true; + output_system& output_sys = __get_output_system__ ("flush_stdout"); - if (! instance) - { - instance = new diary_stream (); + output_sys.flush_stdout (); + } - if (instance) - singleton_cleanup_list::add (cleanup_instance); - } + output_system::output_system (interpreter& interp) + : m_interpreter (interp), m_pager_stream (), m_diary_stream (), + m_external_pager (nullptr), m_external_diary_file (), + m_diary_file_name ("diary"), m_PAGER (default_pager ()), + m_PAGER_FLAGS (), m_page_output_immediately (false), + m_page_screen_output (false), m_write_to_diary_file (false), + m_really_flush_to_pager (false), m_flushing_output_to_pager (false) + { } - if (! instance) - error ("unable to create diary_stream object!"); + octave_value output_system::PAGER (const octave_value_list& args, + int nargout) + { + return set_internal_variable (m_PAGER, args, nargout, "PAGER", false); + } - return retval; + octave_value output_system::PAGER_FLAGS (const octave_value_list& args, + int nargout) + { + return set_internal_variable (m_PAGER_FLAGS, args, nargout, + "PAGER_FLAGS", false); } - void - flush_stdout (void) + octave_value + output_system::page_output_immediately (const octave_value_list& args, + int nargout) + { + return set_internal_variable (m_page_output_immediately, args, nargout, + "page_output_immediately"); + } + + octave_value + output_system::page_screen_output (const octave_value_list& args, + int nargout) + { + return set_internal_variable (m_page_screen_output, args, nargout, + "page_screen_output"); + } + + std::string output_system::pager_command (void) const { - if (! flushing_output_to_pager) + std::string cmd = m_PAGER; + + if (! (cmd.empty () || m_PAGER_FLAGS.empty ())) + cmd += ' ' + m_PAGER_FLAGS; + + return cmd; + } + + void output_system::reset (void) + { + flush_stdout (); + + m_pager_stream.reset (); + m_diary_stream.reset (); + } + + void output_system::flush_stdout (void) + { + if (! m_flushing_output_to_pager) { unwind_protect frame; - frame.protect_var (really_flush_to_pager); - frame.protect_var (flushing_output_to_pager); + frame.protect_var (m_really_flush_to_pager); + frame.protect_var (m_flushing_output_to_pager); - really_flush_to_pager = true; - flushing_output_to_pager = true; + m_really_flush_to_pager = true; + m_flushing_output_to_pager = true; - octave_stdout.flush (); + std::ostream& pager_ostream = m_pager_stream.stream (); + + pager_ostream.flush (); clear_external_pager (); } } -} + + void output_system::close_diary (void) + { + // Try to flush the current buffer to the diary now, so that things + // like + // + // function foo () + // diary on; + // ... + // diary off; + // endfunction + // + // will do the right thing. + + m_pager_stream.flush_current_contents_to_diary (); + + if (m_external_diary_file.is_open ()) + { + octave_diary.flush (); + m_external_diary_file.close (); + } + } + + void output_system::open_diary (void) + { + close_diary (); + + // If there is pending output in the pager buf, it should not go + // into the diary file. + + m_pager_stream.set_diary_skip (); + + m_external_diary_file.open (m_diary_file_name.c_str (), std::ios::app); + + if (! m_external_diary_file) + error ("diary: can't open diary file '%s'", m_diary_file_name.c_str ()); + } -static void -close_diary_file (void) -{ - // Try to flush the current buffer to the diary now, so that things - // like - // - // function foo () - // diary on; - // ... - // diary off; - // endfunction - // - // will do the right thing. + bool output_system::sync (const char *buf, int len) + { + if (! application::interactive () + || application::forced_interactive () + || m_really_flush_to_pager + || (m_page_screen_output && m_page_output_immediately) + || ! m_page_screen_output) + { + bool bypass_pager = (! application::interactive () + || application::forced_interactive () + || ! m_page_screen_output + || (m_really_flush_to_pager + && m_page_screen_output + && ! m_page_output_immediately + && ! more_than_a_screenful (buf, len))); + + if (len > 0) + { + do_sync (buf, len, bypass_pager); - octave::pager_stream::flush_current_contents_to_diary (); + return true; + } + } + + return false; + } + + void output_system::clear_external_pager (void) + { + if (m_external_pager) + { + child_list& kids = m_interpreter.get_child_list (); + + kids.remove (m_external_pager->pid ()); + + delete m_external_pager; + m_external_pager = nullptr; + } + } - if (external_diary_file.is_open ()) - { - octave_diary.flush (); - external_diary_file.close (); - } -} + void output_system::start_external_pager (void) + { + if (m_external_pager) + return; + + std::string pgr = pager_command (); + + if (! pgr.empty ()) + { + m_external_pager = new oprocstream (pgr.c_str ()); + + if (m_external_pager) + { + octave::child_list& kids = m_interpreter.get_child_list (); + + kids.insert (m_external_pager->pid (), + pager_event_handler); + } + } + } + + void output_system::do_sync (const char *msg, int len, bool bypass_pager) + { + if (msg && len > 0) + { + if (bypass_pager) + { + std::cout.write (msg, len); + std::cout.flush (); + } + else + { + start_external_pager (); -static void -open_diary_file (void) -{ - close_diary_file (); + if (m_external_pager) + { + if (m_external_pager->good ()) + { + m_external_pager->write (msg, len); + + m_external_pager->flush (); - // If there is pending output in the pager buf, it should not go - // into the diary file. - - octave::pager_stream::set_diary_skip (); +#if defined (EPIPE) + if (errno == EPIPE) + m_external_pager->setstate (std::ios::failbit); +#endif + } + else + { + // FIXME: something is not right with the + // pager. If it died then we should receive a + // signal for that. If there is some other problem, + // then what? + } + } + else + { + std::cout.write (msg, len); + std::cout.flush (); + } + } + } + } - external_diary_file.open (diary_file.c_str (), std::ios::app); + std::ostream& __stdout__ (void) + { + output_system& output_sys = __get_output_system__ ("__stdout__"); + + return output_sys.__stdout__ (); + } - if (! external_diary_file) - error ("diary: can't open diary file '%s'", diary_file.c_str ()); + std::ostream& __diary__ (void) + { + output_system& output_sys = __get_output_system__ ("__diary__"); + + return output_sys.__diary__ (); + } } DEFUN (diary, args, nargout, @@ -558,22 +533,22 @@ if (nargin > 1) print_usage (); - if (diary_file.empty ()) - diary_file = "diary"; + octave::output_system& output_sys = octave::__get_output_system__ ("Fdiary"); if (nargout > 0) { // Querying diary variables if (nargout == 1) - return ovl (write_to_diary_file); + return ovl (output_sys.write_to_diary_file ()); else - return ovl (write_to_diary_file, diary_file); + return ovl (output_sys.write_to_diary_file (), + output_sys.diary_file_name ()); } if (nargin == 0) { - write_to_diary_file = ! write_to_diary_file; - open_diary_file (); + output_sys.write_to_diary_file (! output_sys.write_to_diary_file ()); + output_sys.open_diary (); } else { @@ -581,27 +556,27 @@ if (arg == "on") { - write_to_diary_file = true; - open_diary_file (); + output_sys.write_to_diary_file (true); + output_sys.open_diary (); } else if (arg == "off") { - close_diary_file (); - write_to_diary_file = false; + output_sys.close_diary (); + output_sys.write_to_diary_file (false); } else { - diary_file = arg; - write_to_diary_file = true; - open_diary_file (); + output_sys.diary_file_name (arg); + output_sys.write_to_diary_file (true); + output_sys.open_diary (); } } return ovl (); } -DEFUN (more, args, , - doc: /* -*- texinfo -*- +DEFMETHOD (more, interp, args, , + doc: /* -*- texinfo -*- @deftypefn {} {} more @deftypefnx {} {} more on @deftypefnx {} {} more off @@ -618,19 +593,21 @@ if (nargin > 1) print_usage (); + octave::output_system& output_sys = interp.get_output_system (); + if (nargin > 0) { std::string arg = args(0).xstring_value (R"(more: argument must be string "on" or "off")"); if (arg == "on") - Vpage_screen_output = true; + output_sys.page_screen_output (true); else if (arg == "off") - Vpage_screen_output = false; + output_sys.page_screen_output (false); else error (R"(more: argument must be "on" or "off")"); } else - Vpage_screen_output = ! Vpage_screen_output; + output_sys.page_screen_output (! output_sys.page_screen_output ()); return ovl (); } @@ -651,8 +628,8 @@ return ovl (size); } -DEFUN (page_output_immediately, args, nargout, - doc: /* -*- texinfo -*- +DEFMETHOD (page_output_immediately, interp, args, nargout, + doc: /* -*- texinfo -*- @deftypefn {} {@var{val} =} page_output_immediately () @deftypefnx {} {@var{old_val} =} page_output_immediately (@var{new_val}) @deftypefnx {} {} page_output_immediately (@var{new_val}, "local") @@ -668,11 +645,13 @@ @seealso{page_screen_output, more, PAGER, PAGER_FLAGS} @end deftypefn */) { - return SET_INTERNAL_VARIABLE (page_output_immediately); + octave::output_system& output_sys = interp.get_output_system (); + + return output_sys.page_output_immediately (args, nargout); } -DEFUN (page_screen_output, args, nargout, - doc: /* -*- texinfo -*- +DEFMETHOD (page_screen_output, interp, args, nargout, + doc: /* -*- texinfo -*- @deftypefn {} {@var{val} =} page_screen_output () @deftypefnx {} {@var{old_val} =} page_screen_output (@var{new_val}) @deftypefnx {} {} page_screen_output (@var{new_val}, "local") @@ -690,11 +669,13 @@ @seealso{more, page_output_immediately, PAGER, PAGER_FLAGS} @end deftypefn */) { - return SET_INTERNAL_VARIABLE (page_screen_output); + octave::output_system& output_sys = interp.get_output_system (); + + return output_sys.page_screen_output (args, nargout); } -DEFUN (PAGER, args, nargout, - doc: /* -*- texinfo -*- +DEFMETHOD (PAGER, interp, args, nargout, + doc: /* -*- texinfo -*- @deftypefn {} {@var{val} =} PAGER () @deftypefnx {} {@var{old_val} =} PAGER (@var{new_val}) @deftypefnx {} {} PAGER (@var{new_val}, "local") @@ -711,11 +692,13 @@ @seealso{PAGER_FLAGS, page_output_immediately, more, page_screen_output} @end deftypefn */) { - return SET_NONEMPTY_INTERNAL_STRING_VARIABLE (PAGER); + octave::output_system& output_sys = interp.get_output_system (); + + return output_sys.PAGER (args, nargout); } -DEFUN (PAGER_FLAGS, args, nargout, - doc: /* -*- texinfo -*- +DEFMETHOD (PAGER_FLAGS, interp, args, nargout, + doc: /* -*- texinfo -*- @deftypefn {} {@var{val} =} PAGER_FLAGS () @deftypefnx {} {@var{old_val} =} PAGER_FLAGS (@var{new_val}) @deftypefnx {} {} PAGER_FLAGS (@var{new_val}, "local") @@ -728,5 +711,7 @@ @seealso{PAGER, more, page_screen_output, page_output_immediately} @end deftypefn */) { - return SET_NONEMPTY_INTERNAL_STRING_VARIABLE (PAGER_FLAGS); + octave::output_system& output_sys = interp.get_output_system (); + + return output_sys.PAGER_FLAGS (args, nargout); }
--- a/libinterp/corefcn/pager.h Sat Mar 17 11:59:05 2018 -0500 +++ b/libinterp/corefcn/pager.h Fri May 25 16:30:01 2018 -0400 @@ -25,14 +25,18 @@ #include "octave-config.h" +#include <fstream> #include <iosfwd> #include <sstream> #include <string> -#include <sys/types.h> +class octave_value; +class oprocstream; namespace octave { + class interpreter; + class OCTINTERP_API pager_buf : public std::stringbuf @@ -58,12 +62,10 @@ OCTINTERP_API pager_stream : public std::ostream { - protected: + public: pager_stream (void); - public: - // No copying! pager_stream (const pager_stream&) = delete; @@ -72,28 +74,16 @@ ~pager_stream (void); - static void flush_current_contents_to_diary (void); + void flush_current_contents_to_diary (void); - static void set_diary_skip (void); + void set_diary_skip (void); - static std::ostream& stream (void); + std::ostream& stream (void); - static void reset (void); + void reset (void); private: - void do_flush_current_contents_to_diary (void); - - void do_set_diary_skip (void); - - void do_reset (void); - - static pager_stream *instance; - - static bool instance_ok (void); - - static void cleanup_instance (void) { delete instance; instance = nullptr; } - pager_buf *pb; }; @@ -114,12 +104,10 @@ OCTINTERP_API diary_stream : public std::ostream { - protected: + public: diary_stream (void); - public: - // No copying! diary_stream (const diary_stream&) = delete; @@ -128,24 +116,194 @@ ~diary_stream (void); - static std::ostream& stream (void); + std::ostream& stream (void); - static void reset (void); + void reset (void); private: - void do_reset (void); - - static diary_stream *instance; - - static bool instance_ok (void); - - static void cleanup_instance (void) { delete instance; instance = nullptr; } - diary_buf *db; }; extern OCTAVE_API void flush_stdout (void); + + class output_system + { + public: + + output_system (interpreter& interp); + + output_system (const output_system&) = delete; + + output_system& operator = (const output_system&) = delete; + + ~output_system (void) = default; + + pager_stream& pager (void) { return m_pager_stream; } + + diary_stream& diary (void) { return m_diary_stream; } + + std::string diary_file_name (void) const { return m_diary_file_name; } + + std::string diary_file_name (const std::string& nm) + { + std::string val = m_diary_file_name; + m_diary_file_name = nm.empty () ? "diary" : nm; + return val; + } + + octave_value PAGER (const octave_value_list& args, int nargout); + + std::string PAGER (void) const { return m_PAGER; } + + std::string PAGER (const std::string& s) + { + std::string val = m_PAGER; + m_PAGER = s; + return val; + } + + octave_value PAGER_FLAGS (const octave_value_list& args, int nargout); + + std::string PAGER_FLAGS (void) const { return m_PAGER_FLAGS; } + + std::string PAGER_FLAGS (const std::string& s) + { + std::string val = m_PAGER_FLAGS; + m_PAGER_FLAGS = s; + return val; + } + + octave_value page_output_immediately (const octave_value_list& args, + int nargout); + + bool page_output_immediately (void) const + { + return m_page_output_immediately; + } + + bool page_output_immediately (bool flag) + { + bool val = m_page_output_immediately; + m_page_output_immediately = flag; + return val; + } + + octave_value page_screen_output (const octave_value_list& args, + int nargout); + + bool page_screen_output (void) const { return m_page_screen_output; } + + bool page_screen_output (bool flag) + { + bool val = m_page_screen_output; + m_page_screen_output = flag; + return val; + } + + bool write_to_diary_file (void) const + { + return m_write_to_diary_file; + } + + bool write_to_diary_file (bool flag) + { + bool val = m_write_to_diary_file; + m_write_to_diary_file = flag; + return val; + } + + bool really_flush_to_pager (void) const + { + return m_really_flush_to_pager; + } + + bool really_flush_to_pager (bool flag) + { + bool val = m_really_flush_to_pager; + m_really_flush_to_pager = flag; + return val; + } + + bool flushing_output_to_pager (void) const + { + return m_flushing_output_to_pager; + } + + bool flushing_output_to_pager (bool flag) + { + bool val = m_flushing_output_to_pager; + m_flushing_output_to_pager = flag; + return val; + } + + std::string pager_command (void) const; + + std::ofstream& external_diary_file (void) { return m_external_diary_file; } + + void reset (void); + + void flush_stdout (void); + + bool sync (const char *msg, int len); + + void clear_external_pager (void); + + void open_diary (void); + + void close_diary (void); + + std::ostream& __stdout__ (void) { return m_pager_stream.stream (); } + + std::ostream& __diary__ (void) { return m_diary_stream.stream (); } + + private: + + interpreter& m_interpreter; + + pager_stream m_pager_stream; + + diary_stream m_diary_stream; + + // Our actual connection to the external pager. + oprocstream *m_external_pager = nullptr; + + // The diary file. + std::ofstream m_external_diary_file; + + // The name of the current diary file. + std::string m_diary_file_name; + + // The shell command to run as the pager. + std::string m_PAGER; + + // The options to pass to the pager. + std::string m_PAGER_FLAGS; + + // TRUE means that if output is going to the pager, it is sent as soon + // as it is available. Otherwise, it is buffered and only sent to the + // pager when it is time to print another prompt. + bool m_page_output_immediately; + + // TRUE means all output intended for the screen should be passed + // through the pager. + bool m_page_screen_output; + + // TRUE means we write to the diary file. + bool m_write_to_diary_file; + + bool m_really_flush_to_pager; + + bool m_flushing_output_to_pager; + + void start_external_pager (void); + + void do_sync (const char *msg, int len, bool bypass_pager); + }; + + extern std::ostream& __stdout__ (void); + + extern std::ostream& __diary__ (void); } #if defined (OCTAVE_USE_DEPRECATED_FUNCTIONS) @@ -171,8 +329,8 @@ #endif -#define octave_stdout (octave::pager_stream::stream ()) +#define octave_stdout (octave::__stdout__ ()) -#define octave_diary (octave::diary_stream::stream ()) +#define octave_diary (octave::__diary__ ()) #endif