GNU Octave  9.1.0
A high-level interpreted language, primarily intended for numerical computations, mostly compatible with Matlab
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