GNU Octave  8.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-2023 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 default_pager (void)
118 {
119  std::string pager_binary = sys::env::getenv ("PAGER");
120 
121  if (pager_binary.empty ())
122  pager_binary = config::default_pager ();
123 
124  return pager_binary;
125 }
126 
127 int
129 {
130  output_system& output_sys = __get_output_system__ ();
131 
132  char *buf = pbase ();
133 
134  int len = pptr () - buf;
135 
136  if (output_sys.sync (buf, len))
137  {
139 
140  seekoff (0, std::ios::beg);
141  }
142 
143  return 0;
144 }
145 
146 void
148 {
149  char *buf = pbase () + m_diary_skip;
150 
151  std::size_t len = pptr () - buf;
152 
153  octave_diary.write (buf, len);
154 
155  m_diary_skip = 0;
156 }
157 
158 void
160 {
161  m_diary_skip = pptr () - pbase ();
162 }
163 
164 int
166 {
167  output_system& output_sys = __get_output_system__ ();
168 
169  std::ofstream& external_diary_file = output_sys.external_diary_file ();
170 
171  if (output_sys.write_to_diary_file () && external_diary_file)
172  {
173  char *buf = pbase ();
174 
175  int len = pptr () - buf;
176 
177  if (len > 0)
178  external_diary_file.write (buf, len);
179  }
180 
181  seekoff (0, std::ios::beg);
182 
183  return 0;
184 }
185 
186 pager_stream::pager_stream (void) : std::ostream (nullptr), m_pb (nullptr)
187 {
188  m_pb = new pager_buf ();
189  rdbuf (m_pb);
190  setf (unitbuf);
191 }
192 
194 {
195  flush ();
196  delete m_pb;
197 }
198 
199 std::ostream& pager_stream::stream (void)
200 {
201  return *this;
202 }
203 
205 {
206  if (m_pb)
208 }
209 
211 {
212  if (m_pb)
213  m_pb->set_diary_skip ();
214 }
215 
216 // Reinitialize the pager buffer to avoid hanging on to large internal
217 // buffers when they might not be needed. This function should only be
218 // called when the pager is not in use. For example, just before
219 // getting command-line input.
220 
222 {
223  delete m_pb;
224  m_pb = new pager_buf ();
225  rdbuf (m_pb);
226  setf (unitbuf);
227 }
228 
229 diary_stream::diary_stream (void) : std::ostream (nullptr), m_db (nullptr)
230 {
231  m_db = new diary_buf ();
232  rdbuf (m_db);
233  setf (unitbuf);
234 }
235 
237 {
238  flush ();
239  delete m_db;
240 }
241 
242 std::ostream& diary_stream::stream (void)
243 {
244  return *this;
245 }
246 
247 // Reinitialize the diary buffer to avoid hanging on to large internal
248 // buffers when they might not be needed. This function should only be
249 // called when the pager is not in use. For example, just before
250 // getting command-line input.
251 
253 {
254  delete m_db;
255  m_db = new diary_buf ();
256  rdbuf (m_db);
257  setf (unitbuf);
258 }
259 
260 void flush_stdout (void)
261 {
262  output_system& output_sys = __get_output_system__ ();
263 
264  output_sys.flush_stdout ();
265 }
266 
268  : m_interpreter (interp), m_pager_stream (), m_diary_stream (),
269  m_external_pager (nullptr), m_external_diary_file (),
270  m_diary_file_name ("diary"), m_PAGER (default_pager ()),
271  m_PAGER_FLAGS (), m_page_output_immediately (false),
272  m_page_screen_output (false), m_write_to_diary_file (false),
273  m_really_flush_to_pager (false), m_flushing_output_to_pager (false)
274 { }
275 
277  int nargout)
278 {
279  return set_internal_variable (m_PAGER, args, nargout, "PAGER", false);
280 }
281 
283  int nargout)
284 {
285  return set_internal_variable (m_PAGER_FLAGS, args, nargout,
286  "PAGER_FLAGS", false);
287 }
288 
291  int nargout)
292 {
293  return set_internal_variable (m_page_output_immediately, args, nargout,
294  "page_output_immediately");
295 }
296 
299  int nargout)
300 {
301  return set_internal_variable (m_page_screen_output, args, nargout,
302  "page_screen_output");
303 }
304 
305 std::string output_system::pager_command (void) const
306 {
307  std::string cmd = m_PAGER;
308 
309  if (! (cmd.empty () || m_PAGER_FLAGS.empty ()))
310  cmd += ' ' + m_PAGER_FLAGS;
311 
312  return cmd;
313 }
314 
316 {
317  flush_stdout ();
318 
321 }
322 
324 {
326  {
329 
332 
333  std::ostream& pager_ostream = m_pager_stream.stream ();
334 
335  pager_ostream.flush ();
336 
338  }
339 }
340 
342 {
343  // Try to flush the current buffer to the diary now, so that things
344  // like
345  //
346  // function foo ()
347  // diary on;
348  // ...
349  // diary off;
350  // endfunction
351  //
352  // will do the right thing.
353 
355 
356  if (m_external_diary_file.is_open ())
357  {
358  octave_diary.flush ();
359  m_external_diary_file.close ();
360  }
361 }
362 
364 {
365  close_diary ();
366 
367  // If there is pending output in the pager buf, it should not go
368  // into the diary file.
369 
371 
372  m_external_diary_file.open (m_diary_file_name.c_str (), std::ios::app);
373 
374  if (! m_external_diary_file)
375  error ("diary: can't open diary file '%s'", m_diary_file_name.c_str ());
376 }
377 
378 bool output_system::sync (const char *buf, int len)
379 {
380  // FIXME: The following seems to be a bit of a mess.
381 
383  || ! m_interpreter.interactive ()
388  {
389  bool bypass_pager = (m_interpreter.server_mode ()
390  || ! m_interpreter.interactive ()
396  && ! more_than_a_screenful (buf, len)));
397 
398  if (len > 0)
399  {
400  do_sync (buf, len, bypass_pager);
401 
402  return true;
403  }
404  }
405 
406  return false;
407 }
408 
410 {
411  if (m_external_pager)
412  {
414 
415  kids.remove (m_external_pager->pid ());
416 
417  delete m_external_pager;
418  m_external_pager = nullptr;
419  }
420 }
421 
423 {
424  if (m_external_pager)
425  return;
426 
427  std::string pgr = pager_command ();
428 
429  if (! pgr.empty ())
430  {
431  m_external_pager = new oprocstream (pgr.c_str ());
432 
434 
435  kids.insert (m_external_pager->pid (),
437  }
438 }
439 
440 void output_system::do_sync (const char *msg, int len, bool bypass_pager)
441 {
442  if (msg && len > 0)
443  {
444  if (bypass_pager)
445  {
446  if (m_interpreter.server_mode ())
447  {
449 
450  evmgr.interpreter_output (std::string (msg, len));
451  }
452  else
453  {
454  std::cout.write (msg, len);
455  std::cout.flush ();
456  }
457  }
458  else
459  {
461 
462  if (m_external_pager)
463  {
464  if (m_external_pager->good ())
465  {
466  m_external_pager->write (msg, len);
467 
468  m_external_pager->flush ();
469 
470 #if defined (EPIPE)
471  if (errno == EPIPE)
472  m_external_pager->setstate (std::ios::failbit);
473 #endif
474  }
475  else
476  {
477  // FIXME: something is not right with the
478  // pager. If it died then we should receive a
479  // signal for that. If there is some other problem,
480  // then what?
481  }
482  }
483  else
484  {
485  std::cout.write (msg, len);
486  std::cout.flush ();
487  }
488  }
489  }
490 }
491 
492 std::ostream& __stdout__ (void)
493 {
494  output_system& output_sys = __get_output_system__ ();
495 
496  return output_sys.__stdout__ ();
497 }
498 
499 std::ostream& __diary__ (void)
500 {
501  output_system& output_sys = __get_output_system__ ();
502 
503  return output_sys.__diary__ ();
504 }
505 
506 DEFMETHOD (diary, interp, args, nargout,
507  doc: /* -*- texinfo -*-
508 @deftypefn {} {} diary
509 @deftypefnx {} {} diary on
510 @deftypefnx {} {} diary off
511 @deftypefnx {} {} diary @var{filename}
512 @deftypefnx {} {[@var{status}, @var{diaryfile}] =} diary
513 Record a list of all commands @emph{and} the output they produce, mixed
514 together just as they appear on the terminal.
515 
516 Valid options are:
517 
518 @table @asis
519 @item on
520 Start recording a session in a file called @file{diary} in the current working
521 directory.
522 
523 @item off
524 Stop recording the session in the diary file.
525 
526 @item @var{filename}
527 Record the session in the file named @var{filename}.
528 @end table
529 
530 With no input or output arguments, @code{diary} toggles the current diary
531 state.
532 
533 If output arguments are requested, @code{diary} ignores inputs and returns
534 the current status. The boolean @var{status} indicates whether recording is on
535 or off, and @var{diaryfile} is the name of the file where the session is
536 stored.
537 @seealso{history, evalc}
538 @end deftypefn */)
539 {
540  int nargin = args.length ();
541 
542  if (nargin > 1)
543  print_usage ();
544 
545  output_system& output_sys = interp.get_output_system ();
546 
547  if (nargout > 0)
548  {
549  // Querying diary variables
550  if (nargout == 1)
551  return ovl (output_sys.write_to_diary_file ());
552  else
553  return ovl (output_sys.write_to_diary_file (),
554  output_sys.diary_file_name ());
555  }
556 
557  if (nargin == 0)
558  {
559  output_sys.write_to_diary_file (! output_sys.write_to_diary_file ());
560  output_sys.open_diary ();
561  }
562  else
563  {
564  std::string arg = args(0).xstring_value ("diary: argument must be a string");
565 
566  if (arg == "on")
567  {
568  output_sys.write_to_diary_file (true);
569  output_sys.open_diary ();
570  }
571  else if (arg == "off")
572  {
573  output_sys.close_diary ();
574  output_sys.write_to_diary_file (false);
575  }
576  else
577  {
578  output_sys.diary_file_name (arg);
579  output_sys.write_to_diary_file (true);
580  output_sys.open_diary ();
581  }
582  }
583 
584  return ovl ();
585 }
586 
587 DEFMETHOD (more, interp, args, ,
588  doc: /* -*- texinfo -*-
589 @deftypefn {} {} more
590 @deftypefnx {} {} more on
591 @deftypefnx {} {} more off
592 Turn output pagination on or off.
593 
594 Without an argument, @code{more} toggles the current state.
595 
596 The current state can be determined via @code{page_screen_output}.
597 @seealso{page_screen_output, page_output_immediately, PAGER, PAGER_FLAGS}
598 @end deftypefn */)
599 {
600  int nargin = args.length ();
601 
602  if (nargin > 1)
603  print_usage ();
604 
605  output_system& output_sys = interp.get_output_system ();
606 
607  if (nargin > 0)
608  {
609  std::string arg = args(0).xstring_value (R"(more: argument must be string "on" or "off")");
610 
611  if (arg == "on")
612  output_sys.page_screen_output (true);
613  else if (arg == "off")
614  output_sys.page_screen_output (false);
615  else
616  error (R"(more: argument must be "on" or "off")");
617  }
618  else
619  output_sys.page_screen_output (! output_sys.page_screen_output ());
620 
621  return ovl ();
622 }
623 
624 DEFUN (terminal_size, args, ,
625  doc: /* -*- texinfo -*-
626 @deftypefn {} {[@var{rows}, @var{cols}] =} terminal_size ()
627 @deftypefnx {} {} terminal_size ([@var{rows}, @var{cols}])
628 Query or set the size of the terminal window. If called with no arguments,
629 return a two-element row vector containing the current size of the terminal
630 window in characters (rows and columns). If called with a two-element vector
631 of integer values, set the terminal size and return the previous setting.
632 Setting the size manually should not be needed when using readline for
633 command-line editing.
634 @seealso{list_in_columns}
635 @end deftypefn */)
636 {
637  int nargin = args.length ();
638 
639  if (nargin > 1)
640  print_usage ();
641 
642  RowVector size (2, 0.0);
643 
644  size(0) = command_editor::terminal_rows ();
645  size(1) = command_editor::terminal_cols ();
646 
647  if (nargin == 1)
648  {
649  Matrix m = args(0).xmatrix_value ("argument must be a 2-element array");
650 
651  if (m.numel () != 2)
652  error ("terminal_size: argument must be a 2-element array");
653 
654  int rows = math::x_nint (m(0));
655  int cols = math::x_nint (m(1));
656 
657  if (rows <= 0 || cols <= 0)
658  error ("terminal_size: rows and columns must be positive integers");
659 
660  command_editor::set_screen_size (rows, cols);
661  }
662 
663  return ovl (size);
664 }
665 
666 DEFMETHOD (page_output_immediately, interp, args, nargout,
667  doc: /* -*- texinfo -*-
668 @deftypefn {} {@var{val} =} page_output_immediately ()
669 @deftypefnx {} {@var{old_val} =} page_output_immediately (@var{new_val})
670 @deftypefnx {} {@var{old_val} =} page_output_immediately (@var{new_val}, "local")
671 Query or set the internal variable that controls whether Octave sends
672 output to the pager as soon as it is available.
673 
674 When the value is @code{false}, Octave buffers its output and waits until just
675 before the prompt is printed to flush it to the pager. This is the default.
676 
677 When @code{page_screen_output} is @code{false}, this variable has no effect.
678 
679 When called from inside a function with the @qcode{"local"} option, the
680 variable is changed locally for the function and any subroutines it calls.
681 The original variable value is restored when exiting the function.
682 @seealso{page_screen_output, more, PAGER, PAGER_FLAGS}
683 @end deftypefn */)
684 {
685  output_system& output_sys = interp.get_output_system ();
686 
687  return output_sys.page_output_immediately (args, nargout);
688 }
689 
690 DEFMETHOD (page_screen_output, interp, args, nargout,
691  doc: /* -*- texinfo -*-
692 @deftypefn {} {@var{val} =} page_screen_output ()
693 @deftypefnx {} {@var{old_val} =} page_screen_output (@var{new_val})
694 @deftypefnx {} {@var{old_val} =} page_screen_output (@var{new_val}, "local")
695 Query or set the internal variable that controls whether output intended
696 for the terminal window that is longer than one page is sent through a
697 pager.
698 
699 This allows you to view one screenful at a time. Some pagers
700 (such as @code{less}---@pxref{Installation}) are also capable of moving
701 backward on the output.
702 
703 When called from inside a function with the @qcode{"local"} option, the
704 variable is changed locally for the function and any subroutines it calls.
705 The original variable value is restored when exiting the function.
706 @seealso{more, page_output_immediately, PAGER, PAGER_FLAGS}
707 @end deftypefn */)
708 {
709  output_system& output_sys = interp.get_output_system ();
710 
711  return output_sys.page_screen_output (args, nargout);
712 }
713 
714 DEFMETHOD (PAGER, interp, args, nargout,
715  doc: /* -*- texinfo -*-
716 @deftypefn {} {@var{val} =} PAGER ()
717 @deftypefnx {} {@var{old_val} =} PAGER (@var{new_val})
718 @deftypefnx {} {@var{old_val} =} PAGER (@var{new_val}, "local")
719 Query or set the internal variable that specifies the program to use
720 to display terminal output on your system.
721 
722 The default value is normally @qcode{"less"}, @qcode{"more"}, or
723 @qcode{"pg"}, depending on what programs are installed on your system.
724 @xref{Installation}.
725 
726 When called from inside a function with the @qcode{"local"} option, the
727 variable is changed locally for the function and any subroutines it calls.
728 The original variable value is restored when exiting the function.
729 @seealso{PAGER_FLAGS, page_output_immediately, more, page_screen_output}
730 @end deftypefn */)
731 {
732  output_system& output_sys = interp.get_output_system ();
733 
734  return output_sys.PAGER (args, nargout);
735 }
736 
737 DEFMETHOD (PAGER_FLAGS, interp, args, nargout,
738  doc: /* -*- texinfo -*-
739 @deftypefn {} {@var{val} =} PAGER_FLAGS ()
740 @deftypefnx {} {@var{old_val} =} PAGER_FLAGS (@var{new_val})
741 @deftypefnx {} {@var{old_val} =} PAGER_FLAGS (@var{new_val}, "local")
742 Query or set the internal variable that specifies the options to pass
743 to the pager.
744 
745 When called from inside a function with the @qcode{"local"} option, the
746 variable is changed locally for the function and any subroutines it calls.
747 The original variable value is restored when exiting the function.
748 @seealso{PAGER, more, page_screen_output, page_output_immediately}
749 @end deftypefn */)
750 {
751  output_system& output_sys = interp.get_output_system ();
752 
753  return output_sys.PAGER_FLAGS (args, nargout);
754 }
755 
OCTAVE_END_NAMESPACE(octave)
Definition: dMatrix.h:42
static bool forced_interactive(void)
Definition: octave.cc:327
void insert(pid_t pid, child::child_event_handler f)
void remove(pid_t pid)
Definition: child-list.cc:35
static int terminal_cols(void)
Definition: cmd-edit.cc:1251
static void set_screen_size(int ht, int wd)
Definition: cmd-edit.cc:1271
static int terminal_rows(void)
Definition: cmd-edit.cc:1245
int sync(void)
Definition: pager.cc:165
diary_stream(void)
Definition: pager.cc:229
void reset(void)
Definition: pager.cc:252
std::ostream & stream(void)
Definition: pager.cc:242
~diary_stream(void)
Definition: pager.cc:236
diary_buf * m_db
Definition: pager.h:129
Provides threadsafe access to octave.
bool interpreter_output(const std::string &msg)
event_manager & get_event_manager(void)
Definition: interpreter.h:328
bool server_mode(void) const
Definition: interpreter.h:169
child_list & get_child_list(void)
Definition: interpreter.h:311
bool interactive(void) const
Definition: interpreter.h:171
pager_stream m_pager_stream
Definition: pager.h:268
std::ofstream & external_diary_file(void)
Definition: pager.h:246
std::string PAGER_FLAGS(void) const
Definition: pager.h:172
std::string PAGER(void) const
Definition: pager.h:161
diary_stream m_diary_stream
Definition: pager.h:270
void close_diary(void)
Definition: pager.cc:341
std::string m_PAGER
Definition: pager.h:282
std::ostream & __diary__(void)
Definition: pager.h:262
bool page_screen_output(void) const
Definition: pager.h:199
void reset(void)
Definition: pager.cc:315
interpreter & m_interpreter
Definition: pager.h:266
std::string diary_file_name(void) const
Definition: pager.h:150
octave_value page_screen_output(const octave_value_list &args, int nargout)
Definition: pager.cc:298
octave_value PAGER_FLAGS(const octave_value_list &args, int nargout)
Definition: pager.cc:282
void open_diary(void)
Definition: pager.cc:363
bool m_flushing_output_to_pager
Definition: pager.h:301
oprocstream * m_external_pager
Definition: pager.h:273
bool sync(const char *msg, int len)
Definition: pager.cc:378
bool write_to_diary_file(void) const
Definition: pager.h:208
void start_external_pager(void)
Definition: pager.cc:422
void clear_external_pager(void)
Definition: pager.cc:409
std::string pager_command(void) const
Definition: pager.cc:305
bool m_page_screen_output
Definition: pager.h:294
void flush_stdout(void)
Definition: pager.cc:323
output_system(interpreter &interp)
Definition: pager.cc:267
std::string m_PAGER_FLAGS
Definition: pager.h:285
octave_value PAGER(const octave_value_list &args, int nargout)
Definition: pager.cc:276
bool page_output_immediately(void) const
Definition: pager.h:184
bool m_really_flush_to_pager
Definition: pager.h:299
std::string m_diary_file_name
Definition: pager.h:279
bool m_page_output_immediately
Definition: pager.h:290
void do_sync(const char *msg, int len, bool bypass_pager)
Definition: pager.cc:440
std::ofstream m_external_diary_file
Definition: pager.h:276
std::ostream & __stdout__(void)
Definition: pager.h:260
octave_value page_output_immediately(const octave_value_list &args, int nargout)
Definition: pager.cc:290
int sync(void)
Definition: pager.cc:128
void set_diary_skip(void)
Definition: pager.cc:159
std::size_t m_diary_skip
Definition: pager.h:62
void flush_current_contents_to_diary(void)
Definition: pager.cc:147
~pager_stream(void)
Definition: pager.cc:193
std::ostream & stream(void)
Definition: pager.cc:199
void flush_current_contents_to_diary(void)
Definition: pager.cc:204
pager_stream(void)
Definition: pager.cc:186
pager_buf * m_pb
Definition: pager.h:91
void set_diary_skip(void)
Definition: pager.cc:210
void reset(void)
Definition: pager.cc:221
pid_t pid(void) const
Definition: procstream.h:65
OCTAVE_BEGIN_NAMESPACE(octave) static octave_value daspk_fcn
OCTINTERP_API 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:979
output_system & __get_output_system__(void)
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:438
T octave_idx_type m
Definition: mx-inlines.cc:773
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:211
std::ostream & __diary__(void)
Definition: pager.cc:499
std::ostream & __stdout__(void)
Definition: pager.cc:492
static std::string default_pager(void)
Definition: pager.cc:117
static bool more_than_a_screenful(const char *s, int len)
Definition: pager.cc:87
static bool pager_event_handler(pid_t pid, int status)
Definition: pager.cc:58
void flush_stdout(void)
Definition: pager.cc:260
#define octave_diary
Definition: pager.h:316
octave_value set_internal_variable(bool &var, const octave_value_list &args, int nargout, const char *nm)
Definition: variables.cc:584
F77_RET_T len
Definition: xerbla.cc:61