GNU Octave  9.1.0
A high-level interpreted language, primarily intended for numerical computations, mostly compatible with Matlab
All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Friends Macros Pages
pager.cc
Go to the documentation of this file.
1 ////////////////////////////////////////////////////////////////////////
2 //
3 // Copyright (C) 1993-2024 The Octave Project Developers
4 //
5 // See the file COPYRIGHT.md in the top-level directory of this
6 // distribution or <https://octave.org/copyright/>.
7 //
8 // This file is part of Octave.
9 //
10 // Octave is free software: you can redistribute it and/or modify it
11 // under the terms of the GNU General Public License as published by
12 // the Free Software Foundation, either version 3 of the License, or
13 // (at your option) any later version.
14 //
15 // Octave is distributed in the hope that it will be useful, but
16 // WITHOUT ANY WARRANTY; without even the implied warranty of
17 // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
18 // GNU General Public License for more details.
19 //
20 // You should have received a copy of the GNU General Public License
21 // along with Octave; see the file COPYING. If not, see
22 // <https://www.gnu.org/licenses/>.
23 //
24 ////////////////////////////////////////////////////////////////////////
25 
26 #if defined (HAVE_CONFIG_H)
27 # include "config.h"
28 #endif
29 
30 #include <fstream>
31 #include <iostream>
32 #include <string>
33 
34 #include "child-list.h"
35 #include "cmd-edit.h"
36 #include "oct-env.h"
37 #include "oct-syscalls.h"
38 
39 #include "defaults.h"
40 #include "defun.h"
41 #include "error.h"
42 #include "errwarn.h"
43 #include "input.h"
44 #include "interpreter.h"
45 #include "interpreter-private.h"
46 #include "octave.h"
47 #include "ovl.h"
48 #include "pager.h"
49 #include "procstream.h"
50 #include "sighandlers.h"
51 #include "unwind-prot.h"
52 #include "utils.h"
53 #include "variables.h"
54 
56 
57 static bool
58 pager_event_handler (pid_t pid, int status)
59 {
60  bool retval = false;
61 
62  if (pid > 0)
63  {
64  if (sys::wifexited (status) || sys::wifsignaled (status))
65  {
66  // Avoid warning() since that will put us back in the pager,
67  // which would be bad news.
68 
69  std::cerr << "warning: connection to external pager lost (pid = "
70  << pid << ')' << std::endl;
71  std::cerr << "warning: flushing pending output (please wait)"
72  << std::endl;
73 
74  // Request removal of this PID from the list of child
75  // processes.
76 
77  retval = true;
78  }
79  }
80 
81  return retval;
82 }
83 
84 // Assume our terminal wraps long lines.
85 
86 static bool
87 more_than_a_screenful (const char *s, int len)
88 {
89  if (s)
90  {
91  int available_rows = command_editor::terminal_rows () - 2;
92 
93  int cols = command_editor::terminal_cols ();
94 
95  int count = 0;
96 
97  int chars_this_line = 0;
98 
99  for (int i = 0; i < len; i++)
100  {
101  if (*s++ == '\n')
102  {
103  count += chars_this_line / cols + 1;
104  chars_this_line = 0;
105  }
106  else
107  chars_this_line++;
108  }
109 
110  if (count > available_rows)
111  return true;
112  }
113 
114  return false;
115 }
116 
117 static std::string
118 default_pager ()
119 {
120  std::string pager_binary = sys::env::getenv ("PAGER");
121 
122  if (pager_binary.empty ())
123  pager_binary = config::default_pager ();
124 
125  return pager_binary;
126 }
127 
128 int
130 {
131  output_system& output_sys = __get_output_system__ ();
132 
133  char *buf = pbase ();
134 
135  int len = pptr () - buf;
136 
137  if (output_sys.sync (buf, len))
138  {
140 
141  seekoff (0, std::ios::beg);
142  }
143 
144  return 0;
145 }
146 
147 void
149 {
150  char *buf = pbase () + m_diary_skip;
151 
152  std::size_t len = pptr () - buf;
153 
154  octave_diary.write (buf, len);
155 
156  m_diary_skip = 0;
157 }
158 
159 void
161 {
162  m_diary_skip = pptr () - pbase ();
163 }
164 
165 int
167 {
168  output_system& output_sys = __get_output_system__ ();
169 
170  std::ofstream& external_diary_file = output_sys.external_diary_file ();
171 
172  if (output_sys.write_to_diary_file () && external_diary_file)
173  {
174  char *buf = pbase ();
175 
176  int len = pptr () - buf;
177 
178  if (len > 0)
179  external_diary_file.write (buf, len);
180  }
181 
182  seekoff (0, std::ios::beg);
183 
184  return 0;
185 }
186 
187 pager_stream::pager_stream () : std::ostream (nullptr), m_pb (nullptr)
188 {
189  m_pb = new pager_buf ();
190  rdbuf (m_pb);
191  setf (unitbuf);
192 }
193 
195 {
196  flush ();
197  delete m_pb;
198 }
199 
200 std::ostream&
202 {
203  return *this;
204 }
205 
206 void
208 {
209  if (m_pb)
211 }
212 
213 void
215 {
216  if (m_pb)
217  m_pb->set_diary_skip ();
218 }
219 
220 // Reinitialize the pager buffer to avoid hanging on to large internal
221 // buffers when they might not be needed. This function should only be
222 // called when the pager is not in use. For example, just before
223 // getting command-line input.
224 
225 void
227 {
228  delete m_pb;
229  m_pb = new pager_buf ();
230  rdbuf (m_pb);
231  setf (unitbuf);
232 }
233 
234 diary_stream::diary_stream () : std::ostream (nullptr), m_db (nullptr)
235 {
236  m_db = new diary_buf ();
237  rdbuf (m_db);
238  setf (unitbuf);
239 }
240 
242 {
243  flush ();
244  delete m_db;
245 }
246 
247 std::ostream&
249 {
250  return *this;
251 }
252 
253 // Reinitialize the diary buffer to avoid hanging on to large internal
254 // buffers when they might not be needed. This function should only be
255 // called when the pager is not in use. For example, just before
256 // getting command-line input.
257 
258 void
260 {
261  delete m_db;
262  m_db = new diary_buf ();
263  rdbuf (m_db);
264  setf (unitbuf);
265 }
266 
267 void
269 {
270  output_system& output_sys = __get_output_system__ ();
271 
272  output_sys.flush_stdout ();
273 }
274 
276  : m_interpreter (interp), m_pager_stream (), m_diary_stream (),
277  m_external_pager (nullptr), m_external_diary_file (),
278  m_diary_file_name ("diary"), m_PAGER (default_pager ()),
279  m_PAGER_FLAGS (), m_page_output_immediately (false),
280  m_page_screen_output (false), m_write_to_diary_file (false),
281  m_really_flush_to_pager (false), m_flushing_output_to_pager (false)
282 { }
283 
286  int nargout)
287 {
288  return set_internal_variable (m_PAGER, args, nargout, "PAGER", false);
289 }
290 
293  int nargout)
294 {
295  return set_internal_variable (m_PAGER_FLAGS, args, nargout,
296  "PAGER_FLAGS", false);
297 }
298 
301  int nargout)
302 {
303  return set_internal_variable (m_page_output_immediately, args, nargout,
304  "page_output_immediately");
305 }
306 
309  int nargout)
310 {
311  return set_internal_variable (m_page_screen_output, args, nargout,
312  "page_screen_output");
313 }
314 
315 std::string
317 {
318  std::string cmd = m_PAGER;
319 
320  if (! (cmd.empty () || m_PAGER_FLAGS.empty ()))
321  cmd += ' ' + m_PAGER_FLAGS;
322 
323  return cmd;
324 }
325 
326 void
328 {
329  flush_stdout ();
330 
331  m_pager_stream.reset ();
332  m_diary_stream.reset ();
333 }
334 
335 void
337 {
338  if (! m_flushing_output_to_pager)
339  {
340  unwind_protect_var<bool> restore_var1 (m_really_flush_to_pager);
341  unwind_protect_var<bool> restore_var2 (m_flushing_output_to_pager);
342 
343  m_really_flush_to_pager = true;
344  m_flushing_output_to_pager = true;
345 
346  std::ostream& pager_ostream = m_pager_stream.stream ();
347 
348  pager_ostream.flush ();
349 
351  }
352 }
353 
354 void
356 {
357  // Try to flush the current buffer to the diary now, so that things
358  // like
359  //
360  // function foo ()
361  // diary on;
362  // ...
363  // diary off;
364  // endfunction
365  //
366  // will do the right thing.
367 
368  m_pager_stream.flush_current_contents_to_diary ();
369 
370  if (m_external_diary_file.is_open ())
371  {
372  octave_diary.flush ();
373  m_external_diary_file.close ();
374  }
375 }
376 
377 void
379 {
380  close_diary ();
381 
382  // If there is pending output in the pager buf, it should not go
383  // into the diary file.
384 
385  m_pager_stream.set_diary_skip ();
386 
387  m_external_diary_file.open (m_diary_file_name.c_str (), std::ios::app);
388 
389  if (! m_external_diary_file)
390  error ("diary: can't open diary file '%s'", m_diary_file_name.c_str ());
391 }
392 
393 bool
394 output_system::sync (const char *buf, int len)
395 {
396  // FIXME: The following seems to be a bit of a mess.
397 
398  if (m_interpreter.server_mode ()
399  || ! m_interpreter.interactive ()
401  || m_really_flush_to_pager
402  || (m_page_screen_output && m_page_output_immediately)
403  || ! m_page_screen_output)
404  {
405  bool bypass_pager = (m_interpreter.server_mode ()
406  || ! m_interpreter.interactive ()
408  || ! m_page_screen_output
409  || (m_really_flush_to_pager
410  && m_page_screen_output
411  && ! m_page_output_immediately
412  && ! more_than_a_screenful (buf, len)));
413 
414  if (len > 0)
415  {
416  do_sync (buf, len, bypass_pager);
417 
418  return true;
419  }
420  }
421 
422  return false;
423 }
424 
425 void
427 {
428  if (m_external_pager)
429  {
430  child_list& kids = m_interpreter.get_child_list ();
431 
432  kids.remove (m_external_pager->pid ());
433 
434  delete m_external_pager;
435  m_external_pager = nullptr;
436  }
437 }
438 
439 void
440 output_system::start_external_pager ()
441 {
442  if (m_external_pager)
443  return;
444 
445  std::string pgr = pager_command ();
446 
447  if (! pgr.empty ())
448  {
449  m_external_pager = new oprocstream (pgr.c_str ());
450 
451  child_list& kids = m_interpreter.get_child_list ();
452 
453  kids.insert (m_external_pager->pid (),
454  pager_event_handler);
455  }
456 }
457 
458 void
459 output_system::do_sync (const char *msg, int len, bool bypass_pager)
460 {
461  if (msg && len > 0)
462  {
463  if (bypass_pager)
464  {
465  if (m_interpreter.server_mode ())
466  {
467  event_manager& evmgr = m_interpreter.get_event_manager ();
468 
469  evmgr.interpreter_output (std::string (msg, len));
470  }
471  else
472  {
473  std::cout.write (msg, len);
474  std::cout.flush ();
475  }
476  }
477  else
478  {
479  start_external_pager ();
480 
481  if (m_external_pager)
482  {
483  if (m_external_pager->good ())
484  {
485  m_external_pager->write (msg, len);
486 
487  m_external_pager->flush ();
488 
489 #if defined (EPIPE)
490  if (errno == EPIPE)
491  m_external_pager->setstate (std::ios::failbit);
492 #endif
493  }
494  else
495  {
496  // FIXME: something is not right with the
497  // pager. If it died then we should receive a
498  // signal for that. If there is some other problem,
499  // then what?
500  }
501  }
502  else
503  {
504  std::cout.write (msg, len);
505  std::cout.flush ();
506  }
507  }
508  }
509 }
510 
511 std::ostream&
513 {
514  output_system& output_sys = __get_output_system__ ();
515 
516  return output_sys.__stdout__ ();
517 }
518 
519 std::ostream&
521 {
522  output_system& output_sys = __get_output_system__ ();
523 
524  return output_sys.__diary__ ();
525 }
526 
527 DEFMETHOD (diary, interp, args, nargout,
528  doc: /* -*- texinfo -*-
529 @deftypefn {} {} diary
530 @deftypefnx {} {} diary on
531 @deftypefnx {} {} diary off
532 @deftypefnx {} {} diary @var{filename}
533 @deftypefnx {} {[@var{status}, @var{diaryfile}] =} diary
534 Record a list of all commands @emph{and} the output they produce, mixed
535 together just as they appear on the terminal.
536 
537 Valid options are:
538 
539 @table @asis
540 @item on
541 Start recording a session in a file called @file{diary} in the current working
542 directory.
543 
544 @item off
545 Stop recording the session in the diary file.
546 
547 @item @var{filename}
548 Record the session in the file named @var{filename}.
549 @end table
550 
551 With no input or output arguments, @code{diary} toggles the current diary
552 state.
553 
554 If output arguments are requested, @code{diary} ignores inputs and returns
555 the current status. The boolean @var{status} indicates whether recording is on
556 or off, and @var{diaryfile} is the name of the file where the session is
557 stored.
558 @seealso{history, evalc}
559 @end deftypefn */)
560 {
561  int nargin = args.length ();
562 
563  if (nargin > 1)
564  print_usage ();
565 
566  output_system& output_sys = interp.get_output_system ();
567 
568  if (nargout > 0)
569  {
570  // Querying diary variables
571  if (nargout == 1)
572  return ovl (output_sys.write_to_diary_file ());
573  else
574  return ovl (output_sys.write_to_diary_file (),
575  output_sys.diary_file_name ());
576  }
577 
578  if (nargin == 0)
579  {
580  output_sys.write_to_diary_file (! output_sys.write_to_diary_file ());
581  output_sys.open_diary ();
582  }
583  else
584  {
585  std::string arg = args(0).xstring_value ("diary: argument must be a string");
586 
587  if (arg == "on")
588  {
589  output_sys.write_to_diary_file (true);
590  output_sys.open_diary ();
591  }
592  else if (arg == "off")
593  {
594  output_sys.close_diary ();
595  output_sys.write_to_diary_file (false);
596  }
597  else
598  {
599  output_sys.diary_file_name (arg);
600  output_sys.write_to_diary_file (true);
601  output_sys.open_diary ();
602  }
603  }
604 
605  return ovl ();
606 }
607 
608 DEFMETHOD (more, interp, args, ,
609  doc: /* -*- texinfo -*-
610 @deftypefn {} {} more
611 @deftypefnx {} {} more on
612 @deftypefnx {} {} more off
613 Turn output pagination on or off.
614 
615 Without an argument, @code{more} toggles the current state.
616 
617 The current state can be determined via @code{page_screen_output}.
618 @seealso{page_screen_output, page_output_immediately, PAGER, PAGER_FLAGS}
619 @end deftypefn */)
620 {
621  int nargin = args.length ();
622 
623  if (nargin > 1)
624  print_usage ();
625 
626  output_system& output_sys = interp.get_output_system ();
627 
628  if (nargin > 0)
629  {
630  std::string arg = args(0).xstring_value (R"(more: argument must be string "on" or "off")");
631 
632  if (arg == "on")
633  output_sys.page_screen_output (true);
634  else if (arg == "off")
635  output_sys.page_screen_output (false);
636  else
637  error (R"(more: argument must be "on" or "off")");
638  }
639  else
640  output_sys.page_screen_output (! output_sys.page_screen_output ());
641 
642  return ovl ();
643 }
644 
645 DEFUN (terminal_size, args, ,
646  doc: /* -*- texinfo -*-
647 @deftypefn {} {[@var{rows}, @var{cols}] =} terminal_size ()
648 @deftypefnx {} {} terminal_size ([@var{rows}, @var{cols}])
649 Query or set the size of the terminal window. If called with no arguments,
650 return a two-element row vector containing the current size of the terminal
651 window in characters (rows and columns). If called with a two-element vector
652 of integer values, set the terminal size and return the previous setting.
653 Setting the size manually should not be needed when using readline for
654 command-line editing.
655 @seealso{list_in_columns}
656 @end deftypefn */)
657 {
658  int nargin = args.length ();
659 
660  if (nargin > 1)
661  print_usage ();
662 
663  RowVector size (2, 0.0);
664 
665  size(0) = command_editor::terminal_rows ();
666  size(1) = command_editor::terminal_cols ();
667 
668  if (nargin == 1)
669  {
670  Matrix m = args(0).xmatrix_value ("argument must be a 2-element array");
671 
672  if (m.numel () != 2)
673  error ("terminal_size: argument must be a 2-element array");
674 
675  int rows = math::x_nint (m(0));
676  int cols = math::x_nint (m(1));
677 
678  if (rows <= 0 || cols <= 0)
679  error ("terminal_size: rows and columns must be positive integers");
680 
681  command_editor::set_screen_size (rows, cols);
682  }
683 
684  return ovl (size);
685 }
686 
687 DEFMETHOD (page_output_immediately, interp, args, nargout,
688  doc: /* -*- texinfo -*-
689 @deftypefn {} {@var{val} =} page_output_immediately ()
690 @deftypefnx {} {@var{old_val} =} page_output_immediately (@var{new_val})
691 @deftypefnx {} {@var{old_val} =} page_output_immediately (@var{new_val}, "local")
692 Query or set the internal variable that controls whether Octave sends
693 output to the pager as soon as it is available.
694 
695 When the value is @code{false}, Octave buffers its output and waits until just
696 before the prompt is printed to flush it to the pager. This is the default.
697 
698 When @code{page_screen_output} is @code{false}, this variable has no effect.
699 
700 When called from inside a function with the @qcode{"local"} option, the
701 variable is changed locally for the function and any subroutines it calls.
702 The original variable value is restored when exiting the function.
703 @seealso{page_screen_output, more, PAGER, PAGER_FLAGS}
704 @end deftypefn */)
705 {
706  output_system& output_sys = interp.get_output_system ();
707 
708  return output_sys.page_output_immediately (args, nargout);
709 }
710 
711 DEFMETHOD (page_screen_output, interp, args, nargout,
712  doc: /* -*- texinfo -*-
713 @deftypefn {} {@var{val} =} page_screen_output ()
714 @deftypefnx {} {@var{old_val} =} page_screen_output (@var{new_val})
715 @deftypefnx {} {@var{old_val} =} page_screen_output (@var{new_val}, "local")
716 Query or set the internal variable that controls whether output intended
717 for the terminal window that is longer than one page is sent through a
718 pager.
719 
720 This allows you to view one screenful at a time. Some pagers
721 (such as @code{less}---@pxref{Installation}) are also capable of moving
722 backward on the output.
723 
724 When called from inside a function with the @qcode{"local"} option, the
725 variable is changed locally for the function and any subroutines it calls.
726 The original variable value is restored when exiting the function.
727 @seealso{more, page_output_immediately, PAGER, PAGER_FLAGS}
728 @end deftypefn */)
729 {
730  output_system& output_sys = interp.get_output_system ();
731 
732  return output_sys.page_screen_output (args, nargout);
733 }
734 
735 DEFMETHOD (PAGER, interp, args, nargout,
736  doc: /* -*- texinfo -*-
737 @deftypefn {} {@var{val} =} PAGER ()
738 @deftypefnx {} {@var{old_val} =} PAGER (@var{new_val})
739 @deftypefnx {} {@var{old_val} =} PAGER (@var{new_val}, "local")
740 Query or set the internal variable that specifies the program to use
741 to display terminal output on your system.
742 
743 The default value is normally @qcode{"less"}, @qcode{"more"}, or
744 @qcode{"pg"}, depending on what programs are installed on your system.
745 @xref{Installation}.
746 
747 When called from inside a function with the @qcode{"local"} option, the
748 variable is changed locally for the function and any subroutines it calls.
749 The original variable value is restored when exiting the function.
750 @seealso{PAGER_FLAGS, page_output_immediately, more, page_screen_output}
751 @end deftypefn */)
752 {
753  output_system& output_sys = interp.get_output_system ();
754 
755  return output_sys.PAGER (args, nargout);
756 }
757 
758 DEFMETHOD (PAGER_FLAGS, interp, args, nargout,
759  doc: /* -*- texinfo -*-
760 @deftypefn {} {@var{val} =} PAGER_FLAGS ()
761 @deftypefnx {} {@var{old_val} =} PAGER_FLAGS (@var{new_val})
762 @deftypefnx {} {@var{old_val} =} PAGER_FLAGS (@var{new_val}, "local")
763 Query or set the internal variable that specifies the options to pass
764 to the pager.
765 
766 When called from inside a function with the @qcode{"local"} option, the
767 variable is changed locally for the function and any subroutines it calls.
768 The original variable value is restored when exiting the function.
769 @seealso{PAGER, more, page_screen_output, page_output_immediately}
770 @end deftypefn */)
771 {
772  output_system& output_sys = interp.get_output_system ();
773 
774  return output_sys.PAGER_FLAGS (args, nargout);
775 }
776 
777 OCTAVE_END_NAMESPACE(octave)
Definition: dMatrix.h:42
static bool forced_interactive()
Definition: octave.cc:329
void insert(pid_t pid, child::child_event_handler f)
void remove(pid_t pid)
Definition: child-list.cc:35
static int terminal_rows()
Definition: cmd-edit.cc:1242
static void set_screen_size(int ht, int wd)
Definition: cmd-edit.cc:1268
static int terminal_cols()
Definition: cmd-edit.cc:1248
int sync()
Definition: pager.cc:166
diary_stream()
Definition: pager.cc:234
void reset()
Definition: pager.cc:259
~diary_stream()
Definition: pager.cc:241
std::ostream & stream()
Definition: pager.cc:248
Provides threadsafe access to octave.
bool interpreter_output(const std::string &msg)
event_manager & get_event_manager()
Definition: interpreter.h:328
bool interactive() const
Definition: interpreter.h:165
child_list & get_child_list()
Definition: interpreter.h:311
bool server_mode() const
Definition: interpreter.h:163
void close_diary()
Definition: pager.cc:355
std::string PAGER_FLAGS() const
Definition: pager.h:167
void open_diary()
Definition: pager.cc:378
bool page_screen_output() const
Definition: pager.h:194
bool page_output_immediately() const
Definition: pager.h:179
void flush_stdout()
Definition: pager.cc:336
std::string diary_file_name() const
Definition: pager.h:145
std::ofstream & external_diary_file()
Definition: pager.h:241
octave_value page_screen_output(const octave_value_list &args, int nargout)
Definition: pager.cc:308
octave_value PAGER_FLAGS(const octave_value_list &args, int nargout)
Definition: pager.cc:292
bool sync(const char *msg, int len)
Definition: pager.cc:394
void reset()
Definition: pager.cc:327
void clear_external_pager()
Definition: pager.cc:426
std::ostream & __stdout__()
Definition: pager.h:255
output_system(interpreter &interp)
Definition: pager.cc:275
octave_value PAGER(const octave_value_list &args, int nargout)
Definition: pager.cc:285
bool write_to_diary_file() const
Definition: pager.h:203
std::string pager_command() const
Definition: pager.cc:316
std::ostream & __diary__()
Definition: pager.h:257
std::string PAGER() const
Definition: pager.h:156
octave_value page_output_immediately(const octave_value_list &args, int nargout)
Definition: pager.cc:300
void flush_current_contents_to_diary()
Definition: pager.cc:148
int sync()
Definition: pager.cc:129
void set_diary_skip()
Definition: pager.cc:160
~pager_stream()
Definition: pager.cc:194
void set_diary_skip()
Definition: pager.cc:214
pager_stream()
Definition: pager.cc:187
void reset()
Definition: pager.cc:226
std::ostream & stream()
Definition: pager.cc:201
void flush_current_contents_to_diary()
Definition: pager.cc:207
pid_t pid() const
Definition: procstream.h:67
OCTAVE_BEGIN_NAMESPACE(octave) static octave_value daspk_fcn
std::string default_pager()
void print_usage(void)
Definition: defun-int.h:72
#define DEFMETHOD(name, interp_name, args_name, nargout_name, doc)
Macro to define a builtin method.
Definition: defun.h:111
#define DEFUN(name, args_name, nargout_name, doc)
Macro to define a builtin function.
Definition: defun.h:56
void() error(const char *fmt,...)
Definition: error.cc:988
output_system & __get_output_system__()
T x_nint(T x)
Definition: lo-mappers.h:269
std::ofstream ofstream(const std::string &filename, const std::ios::openmode mode)
Definition: lo-sysdep.cc:635
T octave_idx_type m
Definition: mx-inlines.cc:781
octave_value set_internal_variable(bool &var, const octave_value_list &args, int nargout, const char *nm)
Definition: variables.cc:583
bool wifexited(int status)
bool wifsignaled(int status)
octave_value_list ovl(const OV_Args &... args)
Construct an octave_value_list with less typing.
Definition: ovl.h:219
std::ostream & __diary__()
std::ostream & __stdout__()
#define octave_diary
Definition: pager.h:311
void flush_stdout()
F77_RET_T len
Definition: xerbla.cc:61