Mercurial > octave
changeset 27930:ea1898178973
simplify handling of temporary output buffer in evalc
* oct-parse.yy (Fevalc): Use stringbuf instead of stringstream.
Eliminate unnecessary try/catch block around call to Feval. Use
single unwind_action object to restore previous output buffers for
octave_stdout and std::cerr.
(restore_octave_stdout, restore_octave_stderr): Delete.
author | John W. Eaton <jwe@octave.org> |
---|---|
date | Fri, 10 Jan 2020 14:19:28 -0500 |
parents | 265b386f8b20 |
children | 0fa21907e54c |
files | libinterp/parse-tree/oct-parse.yy |
diffstat | 1 files changed, 30 insertions(+), 44 deletions(-) [+] |
line wrap: on
line diff
--- a/libinterp/parse-tree/oct-parse.yy Fri Jan 10 12:10:13 2020 -0800 +++ b/libinterp/parse-tree/oct-parse.yy Fri Jan 10 14:19:28 2020 -0500 @@ -5489,20 +5489,6 @@ return interp.evalin (context, try_code, nargout); } -static void -restore_octave_stdout (std::streambuf *buf) -{ - octave_stdout.flush (); - octave_stdout.rdbuf (buf); -} - -static void -restore_octave_stderr (std::streambuf *buf) -{ - std::cerr.flush (); - std::cerr.rdbuf (buf); -} - DEFMETHOD (evalc, interp, args, nargout, doc: /* -*- texinfo -*- @deftypefn {} {@var{s} =} evalc (@var{try}) @@ -5532,44 +5518,44 @@ @seealso{eval, diary} @end deftypefn */) { - octave_value_list retval; - int nargin = args.length (); if (nargin == 0 || nargin > 2) print_usage (); - // redirect stdout/stderr to capturing buffer - std::ostringstream buffer; - - std::ostream& out_stream = octave_stdout; - std::ostream& err_stream = std::cerr; - - out_stream.flush (); - err_stream.flush (); - - std::streambuf* old_out_buf = out_stream.rdbuf (buffer.rdbuf ()); - std::streambuf* old_err_buf = err_stream.rdbuf (buffer.rdbuf ()); - - octave::unwind_protect frame; - - frame.add_fcn (restore_octave_stdout, old_out_buf); - frame.add_fcn (restore_octave_stderr, old_err_buf); - - // call standard eval function + // Flush pending output and redirect stdout/stderr to capturing + // buffer. + + octave_stdout.flush (); + std::cerr.flush (); + + std::stringbuf buffer; + + std::streambuf *old_out_buf = octave_stdout.rdbuf (&buffer); + std::streambuf *old_err_buf = std::cerr.rdbuf (&buffer); + + // Restore previous output buffers no matter how control exits this + // function. There's no need to flush here. That has already + // happened for the normal execution path. If an error happens during + // the eval, then the message is stored in the exception object and we + // will display it later, after the buffers have been restored. + + octave::unwind_action act ([old_out_buf, old_err_buf] (void) + { + octave_stdout.rdbuf (old_out_buf); + std::cerr.rdbuf (old_err_buf); + }); + + // Call standard eval function. int eval_nargout = std::max (0, nargout - 1); - try - { - retval = Feval (interp, args, eval_nargout); - } - catch (const octave::execution_exception& ee) - { - buffer << "error: " << ee.message () << std::endl; - - throw; - } + octave_value_list retval = Feval (interp, args, eval_nargout); + + // Make sure we capture all pending output. + + octave_stdout.flush (); + std::cerr.flush (); retval.prepend (buffer.str ());