GNU Octave  3.8.0
A high-level interpreted language, primarily intended for numerical computations, mostly compatible with Matlab
 All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Properties Friends Macros Pages
toplev.cc
Go to the documentation of this file.
1 /*
2 
3 Copyright (C) 1995-2013 John W. Eaton
4 
5 This file is part of Octave.
6 
7 Octave is free software; you can redistribute it and/or modify it
8 under the terms of the GNU General Public License as published by the
9 Free Software Foundation; either version 3 of the License, or (at your
10 option) any later version.
11 
12 Octave is distributed in the hope that it will be useful, but WITHOUT
13 ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
14 FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
15 for more details.
16 
17 You should have received a copy of the GNU General Public License
18 along with Octave; see the file COPYING. If not, see
19 <http://www.gnu.org/licenses/>.
20 
21 */
22 
23 #ifdef HAVE_CONFIG_H
24 #include <config.h>
25 #endif
26 
27 #include <cassert>
28 #include <cerrno>
29 #include <cstdlib>
30 #include <cstring>
31 #include <new>
32 
33 #include <fstream>
34 #include <iostream>
35 #include <sstream>
36 #include <string>
37 
38 #include <sys/select.h>
39 #include <sys/types.h>
40 #include <unistd.h>
41 
42 #include "cmd-edit.h"
43 #include "cmd-hist.h"
44 #include "file-ops.h"
45 #include "lo-error.h"
46 #include "lo-mappers.h"
47 #include "oct-env.h"
48 #include "oct-locbuf.h"
49 #include "quit.h"
50 #include "singleton-cleanup.h"
51 #include "str-vec.h"
52 
53 #include "defaults.h"
54 #include "defun.h"
55 #include "error.h"
56 #include "file-io.h"
57 #include "graphics.h"
58 #include "input.h"
59 #include "lex.h"
60 #include "load-save.h"
61 #include "octave-link.h"
62 #include "oct-conf.h"
63 #include "oct-conf-features.h"
64 #include "oct-hist.h"
65 #include "oct-map.h"
66 #include "oct-obj.h"
67 #include "ov.h"
68 #include "pager.h"
69 #include "parse.h"
70 #include "pathsearch.h"
71 #include "procstream.h"
72 #include "pt-eval.h"
73 #include "pt-jump.h"
74 #include "pt-stmt.h"
75 #include "sighandlers.h"
76 #include "sysdep.h"
77 #include "syswait.h"
78 #include "toplev.h"
79 #include "unwind-prot.h"
80 #include "utils.h"
81 #include "variables.h"
82 #include "version.h"
83 
84 #ifndef SHELL_PATH
85 #define SHELL_PATH "/bin/sh"
86 #endif
87 
88 void (*octave_exit) (int) = ::exit;
89 
90 // TRUE means the quit() call is allowed.
91 bool quit_allowed = true;
92 
93 // TRUE means we are exiting via the builtin exit or quit functions.
94 bool quitting_gracefully = false;
95 // This stores the exit status.
96 int exit_status = 0;
97 
98 // TRUE means we are ready to interpret commands, but not everything
99 // is ready for interactive use.
101 
102 // TRUE means we've processed all the init code and we are good to go.
103 bool octave_initialized = false;
104 
106 
107 void
109 {
110  instance = new octave_call_stack ();
111 
112  if (instance)
113  {
115 
117  }
118 }
119 
120 int
122 {
123  int retval = -1;
124 
125  if (! cs.empty ())
126  {
127  const call_stack_elt& elt = cs[curr_frame];
128  retval = elt.line;
129  }
130 
131  return retval;
132 }
133 
134 int
136 {
137  int retval = -1;
138 
139  if (! cs.empty ())
140  {
141  const call_stack_elt& elt = cs[curr_frame];
142  retval = elt.column;
143  }
144 
145  return retval;
146 }
147 
148 int
150 {
151  int retval = -1;
152 
153  const_iterator p = cs.end ();
154 
155  while (p != cs.begin ())
156  {
157  const call_stack_elt& elt = *(--p);
158 
159  octave_function *f = elt.fcn;
160 
161  if (f && f->is_user_code ())
162  {
163  if (elt.line > 0)
164  {
165  retval = elt.line;
166  break;
167  }
168  }
169  }
170 
171  return retval;
172 }
173 
174 int
176 {
177  int retval = -1;
178 
179  const_iterator p = cs.end ();
180 
181  while (p != cs.begin ())
182  {
183  const call_stack_elt& elt = *(--p);
184 
185  octave_function *f = elt.fcn;
186 
187  if (f && f->is_user_code ())
188  {
189  if (elt.column)
190  {
191  retval = elt.column;
192  break;
193  }
194  }
195  }
196 
197  return retval;
198 }
199 
200 size_t
202  (octave_idx_type& curr_user_frame) const
203 {
204  size_t retval = 0;
205 
206  curr_user_frame = 0;
207 
208  // Look for the caller of dbstack.
209  size_t frame = cs[curr_frame].prev;
210 
211  bool found = false;
212 
213  size_t k = cs.size ();
214 
215  for (const_reverse_iterator p = cs.rbegin (); p != cs.rend (); p++)
216  {
217  octave_function *f = (*p).fcn;
218 
219  if (--k == frame)
220  found = true;
221 
222  if (f && f->is_user_code ())
223  {
224  if (! found)
225  curr_user_frame++;
226 
227  retval++;
228  }
229  }
230 
231  // We counted how many user frames were not the one, in reverse.
232  // Now set curr_user_frame to be the index in the other direction.
233  curr_user_frame = retval - curr_user_frame - 1;
234 
235  return retval;
236 }
237 
240 {
241  octave_user_code *retval = 0;
242 
243  const_iterator p = cs.end ();
244 
245  while (p != cs.begin ())
246  {
247  const call_stack_elt& elt = *(--p);
248 
249  octave_function *f = elt.fcn;
250 
251  if (f && f->is_user_code ())
252  {
253  if (nskip > 0)
254  nskip--;
255  else
256  {
257  retval = dynamic_cast<octave_user_code *> (f);
258  break;
259  }
260  }
261  }
262 
263  return retval;
264 }
265 
266 // Use static fields for the best efficiency.
267 // NOTE: C++0x will allow these two to be merged into one.
268 static const char *bt_fieldnames[] = { "file", "name", "line",
269  "column", "scope", "context", 0
270  };
271 static const octave_fields bt_fields (bt_fieldnames);
272 
275 {
276  return octave_map (dim_vector (0, 1), bt_fields);
277 }
278 
281  octave_idx_type& curr_user_frame) const
282 {
283  size_t user_code_frames = do_num_user_code_frames (curr_user_frame);
284 
285  size_t nframes = nskip <= user_code_frames ? user_code_frames - nskip : 0;
286 
287  // Our list is reversed.
288  curr_user_frame = nframes - curr_user_frame - 1;
289 
290  octave_map retval (dim_vector (nframes, 1), bt_fields);
291 
292  Cell& file = retval.contents (0);
293  Cell& name = retval.contents (1);
294  Cell& line = retval.contents (2);
295  Cell& column = retval.contents (3);
296  Cell& scope = retval.contents (4);
297  Cell& context = retval.contents (5);
298 
299  if (nframes > 0)
300  {
301  int k = 0;
302 
303  for (const_reverse_iterator p = cs.rbegin (); p != cs.rend (); p++)
304  {
305  const call_stack_elt& elt = *p;
306 
307  octave_function *f = elt.fcn;
308 
309  if (f && f->is_user_code ())
310  {
311  if (nskip > 0)
312  nskip--;
313  else
314  {
315  scope(k) = elt.scope;
316  context(k) = elt.context;
317 
318  file(k) = f->fcn_file_name ();
319  std::string parent_fcn_name = f->parent_fcn_name ();
320  if (parent_fcn_name == std::string ())
321  name(k) = f->name ();
322  else
323  name(k) = f->parent_fcn_name () + Vfilemarker + f->name ();
324 
325  line(k) = elt.line;
326  column(k) = elt.column;
327 
328  k++;
329  }
330  }
331  }
332  }
333 
334  return retval;
335 }
336 
337 bool
338 octave_call_stack::do_goto_frame (size_t n, bool verbose)
339 {
340  bool retval = false;
341 
342  if (n < cs.size ())
343  {
344  retval = true;
345 
346  curr_frame = n;
347 
348  const call_stack_elt& elt = cs[n];
349 
351 
352  if (verbose)
353  {
354  octave_function *f = elt.fcn;
355  std::string nm = f ? f->name () : std::string ("<unknown>");
356 
357  octave_stdout << "stopped in " << nm
358  << " at line " << elt.line
359  << " column " << elt.column
360  << " (" << elt.scope << "[" << elt.context << "])"
361  << std::endl;
362  }
363  }
364 
365  return retval;
366 }
367 
368 bool
370 {
371  bool retval = false;
372 
373  int incr = 0;
374 
375  if (nskip < 0)
376  incr = -1;
377  else if (nskip > 0)
378  incr = 1;
379 
380  // Start looking with the caller of dbup/dbdown/keyboard.
381  size_t frame = cs[curr_frame].prev;
382 
383  while (true)
384  {
385  if ((incr < 0 && frame == 0) || (incr > 0 && frame == cs.size () - 1))
386  break;
387 
388  frame += incr;
389 
390  const call_stack_elt& elt = cs[frame];
391 
392  octave_function *f = elt.fcn;
393 
394  if (frame == 0 || (f && f->is_user_code ()))
395  {
396  if (nskip > 0)
397  nskip--;
398  else if (nskip < 0)
399  nskip++;
400 
401  if (nskip == 0)
402  {
403  curr_frame = frame;
404  cs[cs.size () - 1].prev = curr_frame;
405 
407 
408  if (verbose)
409  {
410  std::ostringstream buf;
411 
412  if (f)
413  buf << "stopped in " << f->name ()
414  << " at line " << elt.line << std::endl;
415  else
416  buf << "at top level" << std::endl;
417 
418  octave_stdout << buf.str ();
419  }
420 
421  retval = true;
422  break;
423  }
424  }
425 
426  // There is no need to set scope and context here. That will
427  // happen when the dbup/dbdown/keyboard frame is popped and we
428  // jump to the new "prev" frame set above.
429  }
430 
431  return retval;
432 }
433 
434 void
436 {
437  size_t frame = curr_frame;
438 
439  bool skipped = false;
440 
441  while (frame != 0)
442  {
443  frame = cs[frame].prev;
444 
445  const call_stack_elt& elt = cs[frame];
446 
447  octave_function *f = elt.fcn;
448 
449  if (frame == 0 || (f && f->is_user_code ()))
450  {
451  if (! skipped)
452  // We found the current user code frame, so skip it.
453  skipped = true;
454  else
455  {
456  // We found the caller user code frame.
457  call_stack_elt tmp (elt);
458  tmp.prev = curr_frame;
459 
460  curr_frame = cs.size ();
461 
462  cs.push_back (tmp);
463 
465 
466  break;
467  }
468  }
469  }
470 }
471 
472 void
474 {
475  call_stack_elt tmp (cs[0]);
476  tmp.prev = curr_frame;
477 
478  curr_frame = cs.size ();
479 
480  cs.push_back (tmp);
481 
483 }
484 
485 void
487 {
488  if (error_state > 0)
489  {
490  error_state = -1;
491 
492  error ("called from:");
493  }
494 
495  if (! cs.empty ())
496  {
497  const call_stack_elt& elt = cs.back ();
498 
499  octave_function *fcn = elt.fcn;
500 
501  std::string fcn_name = "?unknown?";
502 
503  if (fcn)
504  {
505  fcn_name = fcn->fcn_file_name ();
506 
507  if (fcn_name.empty ())
508  fcn_name = fcn->name ();
509  }
510 
511  error (" %s at line %d, column %d",
512  fcn_name.c_str (), elt.line, elt.column);
513  }
514 }
515 
516 void
518 {
519  can_interrupt = true;
526 }
527 
528 int
529 main_loop (void)
530 {
532 
533  can_interrupt = true;
534 
538 
540 
541  octave_initialized = true;
542 
543  // The big loop.
544 
546  ? new octave_lexer ()
547  : new octave_lexer (stdin));
548 
549  octave_parser parser (*lxr);
550 
551  int retval = 0;
552  do
553  {
554  try
555  {
557 
558  parser.reset ();
559 
562 
563  retval = parser.run ();
564 
565  if (retval == 0)
566  {
567  if (parser.stmt_list)
568  {
570 
571  octave_quit ();
572 
573  if (! (interactive || forced_interactive))
574  {
575  bool quit = (tree_return_command::returning
577 
580 
583 
584  if (quit)
585  break;
586  }
587 
588  if (error_state)
589  {
590  if (! (interactive || forced_interactive))
591  {
592  // We should exit with a non-zero status.
593  retval = 1;
594  break;
595  }
596  }
597  else
598  {
601  else
603  }
604  }
605  else if (parser.lexer.end_of_input)
606  break;
607  }
608  }
609  catch (octave_interrupt_exception)
610  {
612  octave_stdout << "\n";
614  return exit_status;
615  }
616  catch (octave_execution_exception)
617  {
619  std::cerr << "error: unhandled execution exception -- trying to return to prompt"
620  << std::endl;
621  }
622  catch (std::bad_alloc)
623  {
625  std::cerr << "error: out of memory -- trying to return to prompt"
626  << std::endl;
627  }
628  }
629  while (retval == 0);
630 
631  if (retval == EOF)
632  retval = 0;
633 
634  return retval;
635 }
636 
637 // Fix up things before exiting.
638 
639 static std::list<std::string> octave_atexit_functions;
640 
641 static void
643 {
644  static bool deja_vu = false;
645 
647 
648  while (! octave_atexit_functions.empty ())
649  {
650  std::string fcn = octave_atexit_functions.front ();
651 
652  octave_atexit_functions.pop_front ();
653 
655 
656  OCTAVE_SAFE_CALL (feval, (fcn, octave_value_list (), 0));
657 
659  }
660 
661  if (! deja_vu)
662  {
663  deja_vu = true;
664 
665  // Process pending events and disasble octave_link event
666  // processing with this call.
667 
669 
670  // Do this explicitly so that destructors for mex file objects
671  // are called, so that functions registered with mexAtExit are
672  // called.
674 
676 
677  // FIXME: is this needed? Can it cause any trouble?
678  OCTAVE_SAFE_CALL (raw_mode, (0));
679 
681 
684 
686 
688 
690 
692 
694 
696 
698 
700 
702  {
703  octave_stdout << "\n";
704 
705  // Yes, we want this to be separate from the call to
706  // flush_octave_stdout above.
707 
709  }
710 
711  // Don't call singleton_cleanup_list::cleanup until we have the
712  // problems with registering/unregistering types worked out. For
713  // example, uncomment the following line, then use the make_int
714  // function from the examples directory to create an integer
715  // object and then exit Octave. Octave should crash with a
716  // segfault when cleaning up the typinfo singleton. We need some
717  // way to force new octave_value_X types that are created in
718  // .oct files to be unregistered when the .oct file shared library
719  // is unloaded.
720  //
721  // OCTAVE_SAFE_CALL (singleton_cleanup_list::cleanup, ());
722 
724  }
725 }
726 
727 void
728 clean_up_and_exit (int retval, bool safe_to_return)
729 {
730  do_octave_atexit ();
731 
732  if (octave_link::exit (retval))
733  {
734  if (safe_to_return)
735  return;
736  else
737  {
738  // What should we do here? We might be called from some
739  // location other than the end of octave_execute_interpreter,
740  // so it might not be safe to return.
741 
742  // We have nothing else to do at this point, and the
743  // octave_link::exit function is supposed to take care of
744  // exiting for us. Assume that job won't take more than a
745  // day...
746 
747  gnulib::sleep (86400);
748  }
749  }
750  else
751  {
752  if (octave_exit)
753  (*octave_exit) (retval);
754  }
755 }
756 
757 DEFUN (quit, args, ,
758  "-*- texinfo -*-\n\
759 @deftypefn {Built-in Function} {} exit (@var{status})\n\
760 @deftypefnx {Built-in Function} {} quit (@var{status})\n\
761 Exit the current Octave session. If the optional integer value\n\
762 @var{status} is supplied, pass that value to the operating system as the\n\
763 Octave's exit status. The default value is zero.\n\
764 @end deftypefn")
765 {
766  octave_value_list retval;
767 
768  if (! quit_allowed)
769  error ("quit: not supported in embedded mode");
770  else
771  {
772  if (args.length () > 0)
773  {
774  int tmp = args(0).nint_value ();
775 
776  if (! error_state)
777  exit_status = tmp;
778  }
779 
780  if (! error_state)
781  {
782  // Instead of simply calling exit, we simulate an interrupt
783  // with a request to exit cleanly so that no matter where the
784  // call to quit occurs, we will run the unwind_protect stack,
785  // clear the OCTAVE_LOCAL_BUFFER allocations, etc. before
786  // exiting.
787 
788  quitting_gracefully = true;
789 
791 
793  }
794  }
795 
796  return retval;
797 }
798 
799 DEFALIAS (exit, quit);
800 
801 DEFUN (warranty, , ,
802  "-*- texinfo -*-\n\
803 @deftypefn {Built-in Function} {} warranty ()\n\
804 Describe the conditions for copying and distributing Octave.\n\
805 @end deftypefn")
806 {
807  octave_value_list retval;
808 
810 \n\
811 GNU Octave free software; you can redistribute it and/or modify\n\
812 it under the terms of the GNU General Public License as published by\n\
813 the Free Software Foundation; either version 3 of the License, or\n\
814 (at your option) any later version.\n\
815 \n\
816 GNU Octave is distributed in the hope that it will be useful,\n\
817 but WITHOUT ANY WARRANTY; without even the implied warranty of\n\
818 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the\n\
819 GNU General Public License for more details.\n\
820 \n\
821 You should have received a copy of the GNU General Public License\n\
822 along with this program. If not, see <http://www.gnu.org/licenses/>.\n\
823 \n";
824 
825  return retval;
826 }
827 
828 // Execute a shell command.
829 
830 static int
831 wait_for_input (int fid)
832 {
833  int retval = -1;
834 
835 #if defined (HAVE_SELECT)
836  if (fid >= 0)
837  {
838  fd_set set;
839 
840  FD_ZERO (&set);
841  FD_SET (fid, &set);
842 
843  retval = gnulib::select (FD_SETSIZE, &set, 0, 0, 0);
844  }
845 #else
846  retval = 1;
847 #endif
848 
849  return retval;
850 }
851 
852 static octave_value_list
853 run_command_and_return_output (const std::string& cmd_str)
854 {
855  octave_value_list retval;
856  unwind_protect frame;
857 
858  iprocstream *cmd = new iprocstream (cmd_str.c_str ());
859 
860  frame.add_delete (cmd);
861  frame.add_fcn (octave_child_list::remove, cmd->pid ());
862 
863  if (*cmd)
864  {
865  int fid = cmd->file_number ();
866 
867  std::ostringstream output_buf;
868 
869  char ch;
870 
871  for (;;)
872  {
873  if (cmd->get (ch))
874  output_buf.put (ch);
875  else
876  {
877  if (! cmd->eof () && errno == EAGAIN)
878  {
879  cmd->clear ();
880 
881  if (wait_for_input (fid) != 1)
882  break;
883  }
884  else
885  break;
886  }
887  }
888 
889  int cmd_status = cmd->close ();
890 
891  if (octave_wait::ifexited (cmd_status))
892  cmd_status = octave_wait::exitstatus (cmd_status);
893  else
894  cmd_status = 127;
895 
896  retval(1) = output_buf.str ();
897  retval(0) = cmd_status;
898  }
899  else
900  error ("unable to start subprocess for '%s'", cmd_str.c_str ());
901 
902  return retval;
903 }
904 
906 
907 DEFUN (system, args, nargout,
908  "-*- texinfo -*-\n\
909 @deftypefn {Built-in Function} {} system (\"@var{string}\")\n\
910 @deftypefnx {Built-in Function} {} system (\"@var{string}\", @var{return_output})\n\
911 @deftypefnx {Built-in Function} {} system (\"@var{string}\", @var{return_output}, @var{type})\n\
912 @deftypefnx {Built-in Function} {[@var{status}, @var{output}] =} system (@dots{})\n\
913 Execute a shell command specified by @var{string}.\n\
914 If the optional argument @var{type} is @qcode{\"async\"}, the process\n\
915 is started in the background and the process ID of the child process\n\
916 is returned immediately. Otherwise, the child process is started and\n\
917 Octave waits until it exits. If the @var{type} argument is omitted, it\n\
918 defaults to the value @qcode{\"sync\"}.\n\
919 \n\
920 If @var{system} is called with one or more output arguments, or if the\n\
921 optional argument @var{return_output} is true and the subprocess is started\n\
922 synchronously, then the output from the command is returned as a variable. \n\
923 Otherwise, if the subprocess is executed synchronously, its output is sent\n\
924 to the standard output. To send the output of a command executed with\n\
925 @code{system} through the pager, use a command like\n\
926 \n\
927 @example\n\
928 @group\n\
929 [output, text] = system (\"cmd\");\n\
930 disp (text);\n\
931 @end group\n\
932 @end example\n\
933 \n\
934 @noindent\n\
935 or\n\
936 \n\
937 @example\n\
938 printf (\"%s\\n\", nthargout (2, \"system\", \"cmd\"));\n\
939 @end example\n\
940 \n\
941 The @code{system} function can return two values. The first is the\n\
942 exit status of the command and the second is any output from the\n\
943 command that was written to the standard output stream. For example,\n\
944 \n\
945 @example\n\
946 [status, output] = system (\"echo foo; exit 2\");\n\
947 @end example\n\
948 \n\
949 @noindent\n\
950 will set the variable @code{output} to the string @samp{foo}, and the\n\
951 variable @code{status} to the integer @samp{2}.\n\
952 \n\
953 For commands run asynchronously, @var{status} is the process id of the\n\
954 command shell that is started to run the command.\n\
955 @seealso{unix, dos}\n\
956 @end deftypefn")
957 {
958  octave_value_list retval;
959 
960  unwind_protect frame;
961 
962  int nargin = args.length ();
963 
964  if (nargin > 0 && nargin < 4)
965  {
966  bool return_output = (nargin == 1 && nargout > 1);
967 
969 
970  if (nargin == 3)
971  {
972  std::string type_str = args(2).string_value ();
973 
974  if (! error_state)
975  {
976  if (type_str == "sync")
977  type = et_sync;
978  else if (type_str == "async")
979  type = et_async;
980  else
981  {
982  error ("system: TYPE must be \"sync\" or \"async\"");
983  return retval;
984  }
985  }
986  else
987  {
988  error ("system: TYPE must be a character string");
989  return retval;
990  }
991  }
992 
993  if (nargin > 1)
994  {
995  return_output = args(1).is_true ();
996 
997  if (error_state)
998  {
999  error ("system: RETURN_OUTPUT must be boolean value true or false");
1000  return retval;
1001  }
1002  }
1003 
1004  if (return_output && type == et_async)
1005  {
1006  error ("system: can't return output from commands run asynchronously");
1007  return retval;
1008  }
1009 
1010  std::string cmd_str = args(0).string_value ();
1011 
1012  if (! error_state)
1013  {
1014 #if defined (__WIN32__) && ! defined (__CYGWIN__)
1015  // Work around weird double-quote handling on Windows systems.
1016  if (type == et_sync)
1017  cmd_str = "\"" + cmd_str + "\"";
1018 #endif
1019 
1020  if (type == et_async)
1021  {
1022  // FIXME: maybe this should go in sysdep.cc?
1023 #ifdef HAVE_FORK
1024  pid_t pid = fork ();
1025 
1026  if (pid < 0)
1027  error ("system: fork failed -- can't create child process");
1028  else if (pid == 0)
1029  {
1030  // FIXME: should probably replace this
1031  // call with something portable.
1032 
1033  execl (SHELL_PATH, "sh", "-c", cmd_str.c_str (),
1034  static_cast<void *> (0));
1035 
1036  panic_impossible ();
1037  }
1038  else
1039  retval(0) = pid;
1040 #elif defined (__WIN32__)
1041  STARTUPINFO si;
1042  PROCESS_INFORMATION pi;
1043  ZeroMemory (&si, sizeof (si));
1044  ZeroMemory (&pi, sizeof (pi));
1045  OCTAVE_LOCAL_BUFFER (char, xcmd_str, cmd_str.length ()+1);
1046  strcpy (xcmd_str, cmd_str.c_str ());
1047 
1048  if (! CreateProcess (0, xcmd_str, 0, 0, FALSE, 0, 0, 0, &si, &pi))
1049  error ("system: CreateProcess failed -- can't create child process");
1050  else
1051  {
1052  retval(0) = pi.dwProcessId;
1053  CloseHandle (pi.hProcess);
1054  CloseHandle (pi.hThread);
1055  }
1056 #else
1057  error ("asynchronous system calls are not supported");
1058 #endif
1059  }
1060  else if (return_output)
1061  retval = run_command_and_return_output (cmd_str);
1062  else
1063  {
1064  int status = system (cmd_str.c_str ());
1065 
1066  // The value in status is as returned by waitpid. If
1067  // the process exited normally, extract the actual exit
1068  // status of the command. Otherwise, return 127 as a
1069  // failure code.
1070 
1071  if (octave_wait::ifexited (status))
1072  status = octave_wait::exitstatus (status);
1073 
1074  retval(0) = status;
1075  }
1076  }
1077  else
1078  error ("system: expecting string as first argument");
1079  }
1080  else
1081  print_usage ();
1082 
1083  return retval;
1084 }
1085 
1086 /*
1087 %!test
1088 %! cmd = ls_command ();
1089 %! [status, output] = system (cmd);
1090 %! assert (status, 0);
1091 %! assert (ischar (output));
1092 %! assert (! isempty (output));
1093 
1094 %!error system ()
1095 %!error system (1, 2, 3)
1096 */
1097 
1098 void
1099 octave_add_atexit_function (const std::string& fname)
1100 {
1101  octave_atexit_functions.push_front (fname);
1102 }
1103 
1104 bool
1105 octave_remove_atexit_function (const std::string& fname)
1106 {
1107  bool found = false;
1108 
1109  for (std::list<std::string>::iterator p = octave_atexit_functions.begin ();
1110  p != octave_atexit_functions.end (); p++)
1111  {
1112  if (*p == fname)
1113  {
1114  octave_atexit_functions.erase (p);
1115  found = true;
1116  break;
1117  }
1118  }
1119 
1120  return found;
1121 }
1122 
1123 
1124 DEFUN (atexit, args, nargout,
1125  "-*- texinfo -*-\n\
1126 @deftypefn {Built-in Function} {} atexit (@var{fcn})\n\
1127 @deftypefnx {Built-in Function} {} atexit (@var{fcn}, @var{flag})\n\
1128 Register a function to be called when Octave exits. For example,\n\
1129 \n\
1130 @example\n\
1131 @group\n\
1132 function last_words ()\n\
1133  disp (\"Bye bye\");\n\
1134 endfunction\n\
1135 atexit (\"last_words\");\n\
1136 @end group\n\
1137 @end example\n\
1138 \n\
1139 @noindent\n\
1140 will print the message @qcode{\"Bye bye\"} when Octave exits.\n\
1141 \n\
1142 The additional argument @var{flag} will register or unregister\n\
1143 @var{fcn} from the list of functions to be called when Octave\n\
1144 exits. If @var{flag} is true, the function is registered, and if\n\
1145 @var{flag} is false, it is unregistered. For example,\n\
1146 after registering the function @code{last_words} above,\n\
1147 \n\
1148 @example\n\
1149 atexit (\"last_words\", false);\n\
1150 @end example\n\
1151 \n\
1152 @noindent\n\
1153 will remove the function from the list and Octave will not call\n\
1154 @code{last_words} when it exits.\n\
1155 \n\
1156 Note that @code{atexit} only removes the first occurrence of a function\n\
1157 from the list, so if a function was placed in the list multiple\n\
1158 times with @code{atexit}, it must also be removed from the list\n\
1159 multiple times.\n\
1160 @end deftypefn")
1161 {
1162  octave_value_list retval;
1163 
1164  int nargin = args.length ();
1165 
1166  if (nargin == 1 || nargin == 2)
1167  {
1168  std::string arg = args(0).string_value ();
1169 
1170  if (! error_state)
1171  {
1172  bool add_mode = true;
1173 
1174  if (nargin == 2)
1175  {
1176  add_mode = args(1).bool_value ();
1177 
1178  if (error_state)
1179  error ("atexit: FLAG argument must be a logical value");
1180  }
1181 
1182  if (! error_state)
1183  {
1184  if (add_mode)
1186  else
1187  {
1188  bool found = octave_remove_atexit_function (arg);
1189 
1190  if (nargout > 0)
1191  retval(0) = found;
1192  }
1193  }
1194  }
1195  else
1196  error ("atexit: FCN argument must be a string");
1197  }
1198  else
1199  print_usage ();
1200 
1201  return retval;
1202 }
1203 
1204 DEFUN (octave_config_info, args, ,
1205  "-*- texinfo -*-\n\
1206 @deftypefn {Built-in Function} {} octave_config_info ()\n\
1207 @deftypefnx {Built-in Function} {} octave_config_info (@var{option})\n\
1208 Return a structure containing configuration and installation\n\
1209 information for Octave.\n\
1210 \n\
1211 If @var{option} is a string, return the configuration information for the\n\
1212 specified option.\n\
1213 \n\
1214 @end deftypefn")
1215 {
1216  octave_value retval;
1217 
1218 #if defined (ENABLE_DYNAMIC_LINKING)
1219  bool octave_supports_dynamic_linking = true;
1220 #else
1221  bool octave_supports_dynamic_linking = false;
1222 #endif
1223 
1224  static bool initialized = false;
1225  static octave_scalar_map m;
1226 
1227  struct conf_info_struct
1228  {
1229  bool subst_home;
1230  const char *key;
1231  const char *val;
1232  };
1233 
1234  static const conf_info_struct conf_info[] =
1235  {
1236  { false, "ALL_CFLAGS", OCTAVE_CONF_ALL_CFLAGS },
1237  { false, "ALL_CXXFLAGS", OCTAVE_CONF_ALL_CXXFLAGS },
1238  { false, "ALL_FFLAGS", OCTAVE_CONF_ALL_FFLAGS },
1239  { false, "ALL_LDFLAGS", OCTAVE_CONF_ALL_LDFLAGS },
1240  { false, "AMD_CPPFLAGS", OCTAVE_CONF_AMD_CPPFLAGS },
1241  { false, "AMD_LDFLAGS", OCTAVE_CONF_AMD_LDFLAGS },
1242  { false, "AMD_LIBS", OCTAVE_CONF_AMD_LIBS },
1243  { false, "AR", OCTAVE_CONF_AR },
1244  { false, "ARFLAGS", OCTAVE_CONF_ARFLAGS },
1245  { false, "ARPACK_CPPFLAGS", OCTAVE_CONF_ARPACK_CPPFLAGS },
1246  { false, "ARPACK_LDFLAGS", OCTAVE_CONF_ARPACK_LDFLAGS },
1247  { false, "ARPACK_LIBS", OCTAVE_CONF_ARPACK_LIBS },
1248  { false, "BLAS_LIBS", OCTAVE_CONF_BLAS_LIBS },
1249  { false, "CAMD_CPPFLAGS", OCTAVE_CONF_CAMD_CPPFLAGS },
1250  { false, "CAMD_LDFLAGS", OCTAVE_CONF_CAMD_LDFLAGS },
1251  { false, "CAMD_LIBS", OCTAVE_CONF_CAMD_LIBS },
1252  { false, "CARBON_LIBS", OCTAVE_CONF_CARBON_LIBS },
1253  { false, "CC", OCTAVE_CONF_CC },
1254  // FIXME: CC_VERSION is deprecated. Remove in version 3.12
1255  { false, "CC_VERSION", OCTAVE_CONF_CC_VERSION },
1256  { false, "CCOLAMD_CPPFLAGS", OCTAVE_CONF_CCOLAMD_CPPFLAGS },
1257  { false, "CCOLAMD_LDFLAGS", OCTAVE_CONF_CCOLAMD_LDFLAGS },
1258  { false, "CCOLAMD_LIBS", OCTAVE_CONF_CCOLAMD_LIBS },
1259  { false, "CFLAGS", OCTAVE_CONF_CFLAGS },
1260  { false, "CHOLMOD_CPPFLAGS", OCTAVE_CONF_CHOLMOD_CPPFLAGS },
1261  { false, "CHOLMOD_LDFLAGS", OCTAVE_CONF_CHOLMOD_LDFLAGS },
1262  { false, "CHOLMOD_LIBS", OCTAVE_CONF_CHOLMOD_LIBS },
1263  { false, "COLAMD_CPPFLAGS", OCTAVE_CONF_COLAMD_CPPFLAGS },
1264  { false, "COLAMD_LDFLAGS", OCTAVE_CONF_COLAMD_LDFLAGS },
1265  { false, "COLAMD_LIBS", OCTAVE_CONF_COLAMD_LIBS },
1266  { false, "CPICFLAG", OCTAVE_CONF_CPICFLAG },
1267  { false, "CPPFLAGS", OCTAVE_CONF_CPPFLAGS },
1268  { false, "CURL_CPPFLAGS", OCTAVE_CONF_CURL_CPPFLAGS },
1269  { false, "CURL_LDFLAGS", OCTAVE_CONF_CURL_LDFLAGS },
1270  { false, "CURL_LIBS", OCTAVE_CONF_CURL_LIBS },
1271  { false, "CXSPARSE_CPPFLAGS", OCTAVE_CONF_CXSPARSE_CPPFLAGS },
1272  { false, "CXSPARSE_LDFLAGS", OCTAVE_CONF_CXSPARSE_LDFLAGS },
1273  { false, "CXSPARSE_LIBS", OCTAVE_CONF_CXSPARSE_LIBS },
1274  { false, "CXX", OCTAVE_CONF_CXX },
1275  { false, "CXXCPP", OCTAVE_CONF_CXXCPP },
1276  { false, "CXXFLAGS", OCTAVE_CONF_CXXFLAGS },
1277  { false, "CXXPICFLAG", OCTAVE_CONF_CXXPICFLAG },
1278  // FIXME: CXX_VERSION is deprecated. Remove in version 3.12
1279  { false, "CXX_VERSION", OCTAVE_CONF_CXX_VERSION },
1280  { false, "DEFAULT_PAGER", OCTAVE_DEFAULT_PAGER },
1281  { false, "DEFS", OCTAVE_CONF_DEFS },
1282  { false, "DL_LD", OCTAVE_CONF_DL_LD },
1283  { false, "DL_LDFLAGS", OCTAVE_CONF_DL_LDFLAGS },
1284  { false, "DL_LIBS", OCTAVE_CONF_DL_LIBS },
1285  { false, "GCC_VERSION", OCTAVE_CONF_GCC_VERSION },
1286  { false, "GXX_VERSION", OCTAVE_CONF_GXX_VERSION },
1287  { false, "ENABLE_DYNAMIC_LINKING", OCTAVE_CONF_ENABLE_DYNAMIC_LINKING },
1288  { false, "EXEEXT", OCTAVE_CONF_EXEEXT },
1289  { false, "F77", OCTAVE_CONF_F77 },
1290  { false, "F77_FLOAT_STORE_FLAG", OCTAVE_CONF_F77_FLOAT_STORE_FLAG },
1291  { false, "F77_INTEGER_8_FLAG", OCTAVE_CONF_F77_INTEGER_8_FLAG },
1292  { false, "FC", OCTAVE_CONF_FC },
1293  { false, "FFLAGS", OCTAVE_CONF_FFLAGS },
1294  { false, "FFTW3_CPPFLAGS", OCTAVE_CONF_FFTW3_CPPFLAGS },
1295  { false, "FFTW3_LDFLAGS", OCTAVE_CONF_FFTW3_LDFLAGS },
1296  { false, "FFTW3_LIBS", OCTAVE_CONF_FFTW3_LIBS },
1297  { false, "FFTW3F_CPPFLAGS", OCTAVE_CONF_FFTW3F_CPPFLAGS },
1298  { false, "FFTW3F_LDFLAGS", OCTAVE_CONF_FFTW3F_LDFLAGS },
1299  { false, "FFTW3F_LIBS", OCTAVE_CONF_FFTW3F_LIBS },
1300  { false, "FLIBS", OCTAVE_CONF_FLIBS },
1301  { false, "FONTCONFIG_CFLAGS", OCTAVE_CONF_FONTCONFIG_CFLAGS },
1302  { false, "FPICFLAG", OCTAVE_CONF_FPICFLAG },
1303  { false, "FT2_CFLAGS", OCTAVE_CONF_FT2_CFLAGS },
1304  { false, "FT2_LIBS", OCTAVE_CONF_FT2_LIBS },
1305  { false, "GLPK_CPPFLAGS", OCTAVE_CONF_GLPK_CPPFLAGS },
1306  { false, "GLPK_LDFLAGS", OCTAVE_CONF_GLPK_LDFLAGS },
1307  { false, "GLPK_LIBS", OCTAVE_CONF_GLPK_LIBS },
1308  { false, "GNUPLOT", OCTAVE_CONF_GNUPLOT },
1309  { false, "GRAPHICS_CFLAGS", OCTAVE_CONF_GRAPHICS_CFLAGS },
1310  { false, "GRAPHICS_LIBS", OCTAVE_CONF_GRAPHICS_LIBS },
1311  { false, "HDF5_CPPFLAGS", OCTAVE_CONF_HDF5_CPPFLAGS },
1312  { false, "HDF5_LDFLAGS", OCTAVE_CONF_HDF5_LDFLAGS },
1313  { false, "HDF5_LIBS", OCTAVE_CONF_HDF5_LIBS },
1314  { false, "LAPACK_LIBS", OCTAVE_CONF_LAPACK_LIBS },
1315  { false, "LDFLAGS", OCTAVE_CONF_LDFLAGS },
1316  { false, "LD_CXX", OCTAVE_CONF_LD_CXX },
1317  { false, "LD_STATIC_FLAG", OCTAVE_CONF_LD_STATIC_FLAG },
1318  { false, "LEX", OCTAVE_CONF_LEX },
1319  { false, "LEXLIB", OCTAVE_CONF_LEXLIB },
1320  { false, "LFLAGS", OCTAVE_CONF_LFLAGS },
1321  { false, "LIBEXT", OCTAVE_CONF_LIBEXT },
1322  { false, "LIBFLAGS", OCTAVE_CONF_LIBFLAGS },
1323  { false, "LIBOCTAVE", OCTAVE_CONF_LIBOCTAVE },
1324  { false, "LIBOCTINTERP", OCTAVE_CONF_LIBOCTINTERP },
1325  { false, "LIBS", OCTAVE_CONF_LIBS },
1326  { false, "LLVM_CPPFLAGS", OCTAVE_CONF_LLVM_CPPFLAGS },
1327  { false, "LLVM_LDFLAGS", OCTAVE_CONF_LLVM_LDFLAGS },
1328  { false, "LLVM_LIBS", OCTAVE_CONF_LLVM_LIBS },
1329  { false, "LN_S", OCTAVE_CONF_LN_S },
1330  { false, "MAGICK_CPPFLAGS", OCTAVE_CONF_MAGICK_CPPFLAGS },
1331  { false, "MAGICK_LDFLAGS", OCTAVE_CONF_MAGICK_LDFLAGS },
1332  { false, "MAGICK_LIBS", OCTAVE_CONF_MAGICK_LIBS },
1333  { false, "MKOCTFILE_DL_LDFLAGS", OCTAVE_CONF_MKOCTFILE_DL_LDFLAGS },
1334  { false, "OCTAVE_LINK_DEPS", OCTAVE_CONF_OCTAVE_LINK_DEPS },
1335  { false, "OCTAVE_LINK_OPTS", OCTAVE_CONF_OCTAVE_LINK_OPTS },
1336  { false, "OCT_LINK_DEPS", OCTAVE_CONF_OCT_LINK_DEPS },
1337  { false, "OCT_LINK_OPTS", OCTAVE_CONF_OCT_LINK_OPTS },
1338  { false, "OPENGL_LIBS", OCTAVE_CONF_OPENGL_LIBS },
1339  { false, "PCRE_CPPFLAGS", OCTAVE_CONF_PCRE_CPPFLAGS },
1340  { false, "PCRE_LIBS", OCTAVE_CONF_PCRE_LIBS },
1341  { false, "PTHREAD_CFLAGS", OCTAVE_CONF_PTHREAD_CFLAGS },
1342  { false, "PTHREAD_LIBS", OCTAVE_CONF_PTHREAD_LIBS },
1343  { false, "QHULL_CPPFLAGS", OCTAVE_CONF_QHULL_CPPFLAGS },
1344  { false, "QHULL_LDFLAGS", OCTAVE_CONF_QHULL_LDFLAGS },
1345  { false, "QHULL_LIBS", OCTAVE_CONF_QHULL_LIBS },
1346  { false, "QRUPDATE_CPPFLAGS", OCTAVE_CONF_QRUPDATE_CPPFLAGS },
1347  { false, "QRUPDATE_LDFLAGS", OCTAVE_CONF_QRUPDATE_LDFLAGS },
1348  { false, "QRUPDATE_LIBS", OCTAVE_CONF_QRUPDATE_LIBS },
1349  { false, "QT_CPPFLAGS", OCTAVE_CONF_QT_CPPFLAGS },
1350  { false, "QT_LDFLAGS", OCTAVE_CONF_QT_LDFLAGS },
1351  { false, "QT_LIBS", OCTAVE_CONF_QT_LIBS },
1352  { false, "RANLIB", OCTAVE_CONF_RANLIB },
1353  { false, "RDYNAMIC_FLAG", OCTAVE_CONF_RDYNAMIC_FLAG },
1354  { false, "READLINE_LIBS", OCTAVE_CONF_READLINE_LIBS },
1355  { false, "SED", OCTAVE_CONF_SED },
1356  { false, "SHARED_LIBS", OCTAVE_CONF_SHARED_LIBS },
1357  { false, "SHLEXT", OCTAVE_CONF_SHLEXT },
1358  { false, "SHLEXT_VER", OCTAVE_CONF_SHLEXT_VER },
1359  { false, "SH_LD", OCTAVE_CONF_SH_LD },
1360  { false, "SH_LDFLAGS", OCTAVE_CONF_SH_LDFLAGS },
1361  { false, "SONAME_FLAGS", OCTAVE_CONF_SONAME_FLAGS },
1362  { false, "STATIC_LIBS", OCTAVE_CONF_STATIC_LIBS },
1363  { false, "TERM_LIBS", OCTAVE_CONF_TERM_LIBS },
1364  { false, "UMFPACK_CPPFLAGS", OCTAVE_CONF_UMFPACK_CPPFLAGS },
1365  { false, "UMFPACK_LDFLAGS", OCTAVE_CONF_UMFPACK_LDFLAGS },
1366  { false, "UMFPACK_LIBS", OCTAVE_CONF_UMFPACK_LIBS },
1367  { false, "USE_64_BIT_IDX_T", OCTAVE_CONF_USE_64_BIT_IDX_T },
1368  { false, "WARN_CFLAGS", OCTAVE_CONF_WARN_CFLAGS },
1369  { false, "WARN_CXXFLAGS", OCTAVE_CONF_WARN_CXXFLAGS },
1370  { false, "X11_INCFLAGS", OCTAVE_CONF_X11_INCFLAGS },
1371  { false, "X11_LIBS", OCTAVE_CONF_X11_LIBS },
1372  { false, "XTRA_CFLAGS", OCTAVE_CONF_XTRA_CFLAGS },
1373  { false, "XTRA_CXXFLAGS", OCTAVE_CONF_XTRA_CXXFLAGS },
1374  { false, "YACC", OCTAVE_CONF_YACC },
1375  { false, "YFLAGS", OCTAVE_CONF_YFLAGS },
1376  { false, "Z_CPPFLAGS", OCTAVE_CONF_Z_CPPFLAGS },
1377  { false, "Z_LDFLAGS", OCTAVE_CONF_Z_LDFLAGS },
1378  { false, "Z_LIBS", OCTAVE_CONF_Z_LIBS },
1379  { false, "api_version", OCTAVE_API_VERSION },
1380  { true, "archlibdir", OCTAVE_ARCHLIBDIR },
1381  { true, "bindir", OCTAVE_BINDIR },
1382  { false, "canonical_host_type", OCTAVE_CANONICAL_HOST_TYPE },
1383  { false, "config_opts", OCTAVE_CONF_config_opts },
1384  { true, "datadir", OCTAVE_DATADIR },
1385  { true, "datarootdir", OCTAVE_DATAROOTDIR },
1386  { true, "exec_prefix", OCTAVE_EXEC_PREFIX },
1387  { true, "fcnfiledir", OCTAVE_FCNFILEDIR },
1388  { true, "imagedir", OCTAVE_IMAGEDIR },
1389  { true, "includedir", OCTAVE_INCLUDEDIR },
1390  { true, "infodir", OCTAVE_INFODIR },
1391  { true, "infofile", OCTAVE_INFOFILE },
1392  { true, "libdir", OCTAVE_LIBDIR },
1393  { true, "libexecdir", OCTAVE_LIBEXECDIR },
1394  { true, "localapiarchlibdir", OCTAVE_LOCALAPIARCHLIBDIR },
1395  { true, "localapifcnfiledir", OCTAVE_LOCALAPIFCNFILEDIR },
1396  { true, "localapioctfiledir", OCTAVE_LOCALAPIOCTFILEDIR },
1397  { true, "localarchlibdir", OCTAVE_LOCALARCHLIBDIR },
1398  { true, "localfcnfiledir", OCTAVE_LOCALFCNFILEDIR },
1399  { true, "localoctfiledir", OCTAVE_LOCALOCTFILEDIR },
1400  { true, "localstartupfiledir", OCTAVE_LOCALSTARTUPFILEDIR },
1401  { true, "localverarchlibdir", OCTAVE_LOCALVERARCHLIBDIR },
1402  { true, "localverfcnfiledir", OCTAVE_LOCALVERFCNFILEDIR },
1403  { true, "localveroctfiledir", OCTAVE_LOCALVEROCTFILEDIR },
1404  { true, "man1dir", OCTAVE_MAN1DIR },
1405  { false, "man1ext", OCTAVE_MAN1EXT },
1406  { true, "mandir", OCTAVE_MANDIR },
1407  { true, "octfiledir", OCTAVE_OCTFILEDIR },
1408  { true, "octetcdir", OCTAVE_OCTETCDIR },
1409  { true, "octincludedir", OCTAVE_OCTINCLUDEDIR },
1410  { true, "octlibdir", OCTAVE_OCTLIBDIR },
1411  { true, "octtestsdir", OCTAVE_OCTTESTSDIR },
1412  { true, "prefix", OCTAVE_PREFIX },
1413  { true, "startupfiledir", OCTAVE_STARTUPFILEDIR },
1414  { false, "version", OCTAVE_VERSION },
1415  { false, 0, 0 }
1416  };
1417 
1418  if (! initialized)
1419  {
1420  m.assign ("dld", octave_value (octave_supports_dynamic_linking));
1421 
1423  m.assign ("float_format",
1425 
1426  m.assign ("words_big_endian",
1428 
1429  m.assign ("words_little_endian",
1431 
1432  m.assign ("features", octave_value (octave_config_features ()));
1433 
1434  int i = 0;
1435 
1436  while (true)
1437  {
1438  const conf_info_struct& elt = conf_info[i++];
1439 
1440  const char *key = elt.key;
1441 
1442  if (key)
1443  {
1444  if (elt.subst_home)
1445  m.assign (key, subst_octave_home (elt.val));
1446  else
1447  m.assign (key, elt.val);
1448  }
1449  else
1450  break;
1451  }
1452 
1453  bool unix_system = true;
1454  bool mac_system = false;
1455  bool windows_system = false;
1456 
1457 #if defined (WIN32)
1458  windows_system = true;
1459 #if !defined (__CYGWIN__)
1460  unix_system = false;
1461 #endif
1462 #endif
1463 
1464 #if defined (OCTAVE_USE_OS_X_API)
1465  mac_system = true;
1466 #endif
1467 
1468  m.assign ("unix", octave_value (unix_system));
1469  m.assign ("mac", octave_value (mac_system));
1470  m.assign ("windows", octave_value (windows_system));
1471 
1472  initialized = true;
1473  }
1474 
1475  int nargin = args.length ();
1476 
1477  if (nargin == 1)
1478  {
1479  std::string arg = args(0).string_value ();
1480 
1481  if (! error_state)
1482  {
1483  if (m.isfield (arg))
1484  {
1485  Cell c = m.contents (arg);
1486 
1487  if (c.is_empty ())
1488  error ("octave_config_info: no info for '%s'", arg.c_str ());
1489  else
1490  retval = c(0);
1491  }
1492  else
1493  error ("octave_config_info: invalid parameter '%s'", arg.c_str ());
1494  }
1495  }
1496  else if (nargin == 0)
1497  retval = m;
1498  else
1499  print_usage ();
1500 
1501  return retval;
1502 }
1503 
1504 /*
1505 %!assert (ischar (octave_config_info ("version")))
1506 %!test
1507 %! x = octave_config_info ();
1508 %! assert (isstruct (x));
1509 %! assert (! isempty (x));
1510 
1511 %!error octave_config_info (1, 2)
1512 */
1513 
1514 #if defined (__GNUG__) && defined (DEBUG_NEW_DELETE)
1515 
1516 int debug_new_delete = 0;
1517 
1518 typedef void (*vfp)(void);
1519 extern vfp __new_handler;
1520 
1521 void *
1522 __builtin_new (size_t sz)
1523 {
1524  void *p;
1525 
1526  /* malloc (0) is unpredictable; avoid it. */
1527  if (sz == 0)
1528  sz = 1;
1529  p = gnulib::malloc (sz);
1530  while (p == 0)
1531  {
1532  (*__new_handler) ();
1533  p = gnulib::malloc (sz);
1534  }
1535 
1536  if (debug_new_delete)
1537  std::cerr << "__builtin_new: " << p << std::endl;
1538 
1539  return p;
1540 }
1541 
1542 void
1543 __builtin_delete (void *ptr)
1544 {
1545  if (debug_new_delete)
1546  std::cerr << "__builtin_delete: " << ptr << std::endl;
1547 
1548  if (ptr)
1549  free (ptr);
1550 }
1551 
1552 #endif