00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019
00020
00021
00022
00023 #ifdef HAVE_CONFIG_H
00024 #include <config.h>
00025 #endif
00026
00027 #include <cassert>
00028 #include <cerrno>
00029 #include <cstdlib>
00030 #include <cstring>
00031 #include <new>
00032
00033 #include <fstream>
00034 #include <iostream>
00035 #include <sstream>
00036 #include <string>
00037
00038 #include <sys/types.h>
00039 #include <unistd.h>
00040
00041 #include "cmd-edit.h"
00042 #include "cmd-hist.h"
00043 #include "file-ops.h"
00044 #include "lo-error.h"
00045 #include "lo-mappers.h"
00046 #include "oct-env.h"
00047 #include "oct-locbuf.h"
00048 #include "quit.h"
00049 #include "singleton-cleanup.h"
00050 #include "str-vec.h"
00051
00052 #include "defaults.h"
00053 #include "defun.h"
00054 #include "error.h"
00055 #include "file-io.h"
00056 #include "graphics.h"
00057 #include "input.h"
00058 #include "lex.h"
00059 #include "oct-conf.h"
00060 #include "oct-hist.h"
00061 #include "oct-map.h"
00062 #include "oct-obj.h"
00063 #include "ov.h"
00064 #include "pager.h"
00065 #include "parse.h"
00066 #include "pathsearch.h"
00067 #include "procstream.h"
00068 #include "pt-eval.h"
00069 #include "pt-jump.h"
00070 #include "pt-stmt.h"
00071 #include "sighandlers.h"
00072 #include "sysdep.h"
00073 #include "syswait.h"
00074 #include "toplev.h"
00075 #include "unwind-prot.h"
00076 #include "utils.h"
00077 #include "variables.h"
00078 #include "version.h"
00079
00080 void (*octave_exit) (int) = ::exit;
00081
00082
00083 bool quit_allowed = true;
00084
00085
00086 bool quitting_gracefully = false;
00087
00088 int exit_status = 0;
00089
00090
00091
00092 bool octave_interpreter_ready = false;
00093
00094
00095 bool octave_initialized = false;
00096
00097
00098 tree_statement_list *global_command = 0;
00099
00100 octave_call_stack *octave_call_stack::instance = 0;
00101
00102 void
00103 octave_call_stack::create_instance (void)
00104 {
00105 instance = new octave_call_stack ();
00106
00107 if (instance)
00108 {
00109 instance->do_push (0, symbol_table::top_scope (), 0);
00110
00111 singleton_cleanup_list::add (cleanup_instance);
00112 }
00113 }
00114
00115 int
00116 octave_call_stack::do_current_line (void) const
00117 {
00118 tree_statement *stmt = do_current_statement ();
00119
00120 return stmt ? stmt->line () : -1;
00121 }
00122
00123 int
00124 octave_call_stack::do_current_column (void) const
00125 {
00126 tree_statement *stmt = do_current_statement ();
00127
00128 return stmt ? stmt->column () : -1;
00129 }
00130
00131 int
00132 octave_call_stack::do_caller_user_code_line (void) const
00133 {
00134 int retval = -1;
00135
00136 const_iterator p = cs.end ();
00137
00138 while (p != cs.begin ())
00139 {
00140 const call_stack_elt& elt = *(--p);
00141
00142 octave_function *f = elt.fcn;
00143
00144 if (f && f->is_user_code ())
00145 {
00146 tree_statement *stmt = elt.stmt;
00147
00148 if (stmt)
00149 {
00150 retval = stmt->line ();
00151 break;
00152 }
00153 }
00154 }
00155
00156 return retval;
00157 }
00158
00159 int
00160 octave_call_stack::do_caller_user_code_column (void) const
00161 {
00162 int retval = -1;
00163
00164 const_iterator p = cs.end ();
00165
00166 while (p != cs.begin ())
00167 {
00168 const call_stack_elt& elt = *(--p);
00169
00170 octave_function *f = elt.fcn;
00171
00172 if (f && f->is_user_code ())
00173 {
00174 tree_statement *stmt = elt.stmt;
00175
00176 if (stmt)
00177 {
00178 retval = stmt->column ();
00179 break;
00180 }
00181 }
00182 }
00183
00184 return retval;
00185 }
00186
00187 size_t
00188 octave_call_stack::do_num_user_code_frames (octave_idx_type& curr_user_frame) const
00189 {
00190 size_t retval = 0;
00191
00192 curr_user_frame = 0;
00193
00194
00195 size_t frame = cs[curr_frame].prev;
00196
00197 bool found = false;
00198
00199 size_t k = cs.size ();
00200
00201 for (const_reverse_iterator p = cs.rbegin (); p != cs.rend (); p++)
00202 {
00203 octave_function *f = (*p).fcn;
00204
00205 if (--k == frame)
00206 found = true;
00207
00208 if (f && f->is_user_code ())
00209 {
00210 if (! found)
00211 curr_user_frame++;
00212
00213 retval++;
00214 }
00215 }
00216
00217
00218
00219 curr_user_frame = retval - curr_user_frame - 1;
00220
00221 return retval;
00222 }
00223
00224 octave_user_code *
00225 octave_call_stack::do_caller_user_code (size_t nskip) const
00226 {
00227 octave_user_code *retval = 0;
00228
00229 const_iterator p = cs.end ();
00230
00231 while (p != cs.begin ())
00232 {
00233 const call_stack_elt& elt = *(--p);
00234
00235 octave_function *f = elt.fcn;
00236
00237 if (f && f->is_user_code ())
00238 {
00239 if (nskip > 0)
00240 nskip--;
00241 else
00242 {
00243 retval = dynamic_cast<octave_user_code *> (f);
00244 break;
00245 }
00246 }
00247 }
00248
00249 return retval;
00250 }
00251
00252
00253
00254 static const char *bt_fieldnames[] = { "file", "name", "line",
00255 "column", "scope", "context", 0 };
00256 static const octave_fields bt_fields (bt_fieldnames);
00257
00258 octave_map
00259 octave_call_stack::empty_backtrace (void)
00260 {
00261 return octave_map (dim_vector (0, 1), bt_fields);
00262 }
00263
00264 octave_map
00265 octave_call_stack::do_backtrace (size_t nskip,
00266 octave_idx_type& curr_user_frame) const
00267 {
00268 size_t user_code_frames = do_num_user_code_frames (curr_user_frame);
00269
00270 size_t nframes = nskip <= user_code_frames ? user_code_frames - nskip : 0;
00271
00272
00273 curr_user_frame = nframes - curr_user_frame - 1;
00274
00275 octave_map retval (dim_vector (nframes, 1), bt_fields);
00276
00277 Cell& file = retval.contents (0);
00278 Cell& name = retval.contents (1);
00279 Cell& line = retval.contents (2);
00280 Cell& column = retval.contents (3);
00281 Cell& scope = retval.contents (4);
00282 Cell& context = retval.contents (5);
00283
00284 if (nframes > 0)
00285 {
00286 int k = 0;
00287
00288 for (const_reverse_iterator p = cs.rbegin (); p != cs.rend (); p++)
00289 {
00290 const call_stack_elt& elt = *p;
00291
00292 octave_function *f = elt.fcn;
00293
00294 if (f && f->is_user_code ())
00295 {
00296 if (nskip > 0)
00297 nskip--;
00298 else
00299 {
00300 scope(k) = elt.scope;
00301 context(k) = elt.context;
00302
00303 file(k) = f->fcn_file_name ();
00304 std::string parent_fcn_name = f->parent_fcn_name ();
00305 if (parent_fcn_name == std::string ())
00306 name(k) = f->name ();
00307 else
00308 name(k) = f->parent_fcn_name () + Vfilemarker + f->name ();
00309
00310 tree_statement *stmt = elt.stmt;
00311
00312 if (stmt)
00313 {
00314 line(k) = stmt->line ();
00315 column(k) = stmt->column ();
00316 }
00317 else
00318 {
00319 line(k) = -1;
00320 column(k) = -1;
00321 }
00322
00323 k++;
00324 }
00325 }
00326 }
00327 }
00328
00329 return retval;
00330 }
00331
00332 bool
00333 octave_call_stack::do_goto_frame (size_t n, bool verbose)
00334 {
00335 bool retval = false;
00336
00337 if (n < cs.size ())
00338 {
00339 retval = true;
00340
00341 curr_frame = n;
00342
00343 const call_stack_elt& elt = cs[n];
00344
00345 symbol_table::set_scope_and_context (elt.scope, elt.context);
00346
00347 if (verbose)
00348 {
00349 octave_function *f = elt.fcn;
00350 std::string nm = f ? f->name () : std::string ("<unknown>");
00351
00352 tree_statement *s = elt.stmt;
00353 int l = -1;
00354 int c = -1;
00355 if (s)
00356 {
00357 l = s->line ();
00358 c = s->column ();
00359 }
00360
00361 octave_stdout << "stopped in " << nm
00362 << " at line " << l << " column " << c
00363 << " (" << elt.scope << "[" << elt.context << "])"
00364 << std::endl;
00365 }
00366 }
00367
00368 return retval;
00369 }
00370
00371 bool
00372 octave_call_stack::do_goto_frame_relative (int nskip, bool verbose)
00373 {
00374 bool retval = false;
00375
00376 int incr = 0;
00377
00378 if (nskip < 0)
00379 incr = -1;
00380 else if (nskip > 0)
00381 incr = 1;
00382
00383
00384 size_t frame = cs[curr_frame].prev;
00385
00386 while (true)
00387 {
00388 if ((incr < 0 && frame == 0) || (incr > 0 && frame == cs.size () - 1))
00389 break;
00390
00391 frame += incr;
00392
00393 const call_stack_elt& elt = cs[frame];
00394
00395 octave_function *f = elt.fcn;
00396
00397 if (frame == 0 || (f && f->is_user_code ()))
00398 {
00399 if (nskip > 0)
00400 nskip--;
00401 else if (nskip < 0)
00402 nskip++;
00403
00404 if (nskip == 0)
00405 {
00406 curr_frame = frame;
00407 cs[cs.size () - 1].prev = curr_frame;
00408
00409 symbol_table::set_scope_and_context (elt.scope, elt.context);
00410
00411 if (verbose)
00412 {
00413 std::ostringstream buf;
00414
00415 if (f)
00416 {
00417 tree_statement *s = elt.stmt;
00418
00419 int l = s ? s->line () : -1;
00420
00421 buf << "stopped in " << f->name ()
00422 << " at line " << l << std::endl;
00423 }
00424 else
00425 buf << "at top level" << std::endl;
00426
00427 octave_stdout << buf.str ();
00428 }
00429
00430 retval = true;
00431 break;
00432 }
00433 }
00434
00435
00436
00437
00438 }
00439
00440 return retval;
00441 }
00442
00443 void
00444 octave_call_stack::do_goto_caller_frame (void)
00445 {
00446 size_t frame = curr_frame;
00447
00448 bool skipped = false;
00449
00450 while (frame != 0)
00451 {
00452 frame = cs[frame].prev;
00453
00454 const call_stack_elt& elt = cs[frame];
00455
00456 octave_function *f = elt.fcn;
00457
00458 if (frame == 0 || (f && f->is_user_code ()))
00459 {
00460 if (! skipped)
00461
00462 skipped = true;
00463 else
00464 {
00465
00466 call_stack_elt tmp (elt);
00467 tmp.prev = curr_frame;
00468
00469 curr_frame = cs.size ();
00470
00471 cs.push_back (tmp);
00472
00473 symbol_table::set_scope_and_context (tmp.scope, tmp.context);
00474
00475 break;
00476 }
00477 }
00478 }
00479 }
00480
00481 void
00482 octave_call_stack::do_goto_base_frame (void)
00483 {
00484 call_stack_elt tmp (cs[0]);
00485 tmp.prev = curr_frame;
00486
00487 curr_frame = cs.size ();
00488
00489 cs.push_back (tmp);
00490
00491 symbol_table::set_scope_and_context (tmp.scope, tmp.context);
00492 }
00493
00494 void
00495 octave_call_stack::do_backtrace_error_message (void) const
00496 {
00497 if (error_state > 0)
00498 {
00499 error_state = -1;
00500
00501 error ("called from:");
00502 }
00503
00504 if (! cs.empty ())
00505 {
00506 const call_stack_elt& elt = cs.back ();
00507
00508 octave_function *fcn = elt.fcn;
00509 tree_statement *stmt = elt.stmt;
00510
00511 std::string fcn_name = "?unknown?";
00512
00513 if (fcn)
00514 {
00515 fcn_name = fcn->fcn_file_name ();
00516
00517 if (fcn_name.empty ())
00518 fcn_name = fcn->name ();
00519 }
00520
00521 int line = stmt ? stmt->line () : -1;
00522 int column = stmt ? stmt->column () : -1;
00523
00524 error (" %s at line %d, column %d",
00525 fcn_name.c_str (), line, column);
00526 }
00527 }
00528
00529 void
00530 recover_from_exception (void)
00531 {
00532 can_interrupt = true;
00533 octave_interrupt_immediately = 0;
00534 octave_interrupt_state = 0;
00535 octave_signal_caught = 0;
00536 octave_exception_state = octave_no_exception;
00537 octave_restore_signal_mask ();
00538 octave_catch_interrupts ();
00539 }
00540
00541 int
00542 main_loop (void)
00543 {
00544 octave_save_signal_mask ();
00545
00546 can_interrupt = true;
00547
00548 octave_signal_hook = octave_signal_handler;
00549 octave_interrupt_hook = 0;
00550 octave_bad_alloc_hook = 0;
00551
00552 octave_catch_interrupts ();
00553
00554 octave_initialized = true;
00555
00556
00557
00558 int retval = 0;
00559 do
00560 {
00561 try
00562 {
00563 unwind_protect frame;
00564
00565 reset_error_handler ();
00566
00567 reset_parser ();
00568
00569 if (symbol_table::at_top_level ())
00570 tree_evaluator::reset_debug_state ();
00571
00572
00573
00574
00575 symbol_table::scope_id scope = symbol_table::top_scope ();
00576 frame.add_fcn (symbol_table::unmark_forced_variables, scope);
00577
00578 frame.protect_var (global_command);
00579
00580 global_command = 0;
00581
00582
00583 retval = octave_parse ();
00584
00585 if (retval == 0)
00586 {
00587 if (global_command)
00588 {
00589
00590
00591
00592
00593 frame.add_fcn (cleanup_statement_list, &global_command);
00594
00595 global_command->accept (*current_evaluator);
00596
00597 octave_quit ();
00598
00599 if (! (interactive || forced_interactive))
00600 {
00601 bool quit = (tree_return_command::returning
00602 || tree_break_command::breaking);
00603
00604 if (tree_return_command::returning)
00605 tree_return_command::returning = 0;
00606
00607 if (tree_break_command::breaking)
00608 tree_break_command::breaking--;
00609
00610 if (quit)
00611 break;
00612 }
00613
00614 if (error_state)
00615 {
00616 if (! (interactive || forced_interactive))
00617 {
00618
00619 retval = 1;
00620 break;
00621 }
00622 }
00623 else
00624 {
00625 if (octave_completion_matches_called)
00626 octave_completion_matches_called = false;
00627 else
00628 command_editor::increment_current_command_number ();
00629 }
00630 }
00631 else if (parser_end_of_input)
00632 break;
00633 }
00634 }
00635 catch (octave_interrupt_exception)
00636 {
00637 recover_from_exception ();
00638 octave_stdout << "\n";
00639 if (quitting_gracefully)
00640 {
00641 clean_up_and_exit (exit_status);
00642 break;
00643 }
00644 }
00645 catch (octave_execution_exception)
00646 {
00647 recover_from_exception ();
00648 std::cerr
00649 << "error: unhandled execution exception -- trying to return to prompt"
00650 << std::endl;
00651 }
00652 catch (std::bad_alloc)
00653 {
00654 recover_from_exception ();
00655 std::cerr
00656 << "error: memory exhausted or requested size too large for range of Octave's index type -- trying to return to prompt"
00657 << std::endl;
00658 }
00659 }
00660 while (retval == 0);
00661
00662 return retval;
00663 }
00664
00665
00666
00667 void
00668 clean_up_and_exit (int retval)
00669 {
00670 do_octave_atexit ();
00671
00672 if (octave_exit)
00673 (*octave_exit) (retval == EOF ? 0 : retval);
00674 }
00675
00676 DEFUN (quit, args, ,
00677 "-*- texinfo -*-\n\
00678 @deftypefn {Built-in Function} {} exit (@var{status})\n\
00679 @deftypefnx {Built-in Function} {} quit (@var{status})\n\
00680 Exit the current Octave session. If the optional integer value\n\
00681 @var{status} is supplied, pass that value to the operating system as the\n\
00682 Octave's exit status. The default value is zero.\n\
00683 @end deftypefn")
00684 {
00685 octave_value_list retval;
00686
00687 if (! quit_allowed)
00688 error ("quit: not supported in embedded mode");
00689 else
00690 {
00691 if (args.length () > 0)
00692 {
00693 int tmp = args(0).nint_value ();
00694
00695 if (! error_state)
00696 exit_status = tmp;
00697 }
00698
00699 if (! error_state)
00700 {
00701
00702
00703
00704
00705
00706
00707 quitting_gracefully = true;
00708
00709 octave_interrupt_state = -1;
00710
00711 octave_throw_interrupt_exception ();
00712 }
00713 }
00714
00715 return retval;
00716 }
00717
00718 DEFALIAS (exit, quit);
00719
00720 DEFUN (warranty, , ,
00721 "-*- texinfo -*-\n\
00722 @deftypefn {Built-in Function} {} warranty ()\n\
00723 Describe the conditions for copying and distributing Octave.\n\
00724 @end deftypefn")
00725 {
00726 octave_value_list retval;
00727
00728 octave_stdout << "\n" \
00729 OCTAVE_NAME_VERSION_AND_COPYRIGHT "\n\
00730 \n\
00731 GNU Octave free software; you can redistribute it and/or modify\n\
00732 it under the terms of the GNU General Public License as published by\n\
00733 the Free Software Foundation; either version 3 of the License, or\n\
00734 (at your option) any later version.\n\
00735 \n\
00736 GNU Octave is distributed in the hope that it will be useful,\n\
00737 but WITHOUT ANY WARRANTY; without even the implied warranty of\n\
00738 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the\n\
00739 GNU General Public License for more details.\n\
00740 \n\
00741 You should have received a copy of the GNU General Public License\n\
00742 along with this program. If not, see <http://www.gnu.org/licenses/>.\n\
00743 \n";
00744
00745 return retval;
00746 }
00747
00748
00749
00750 static int
00751 wait_for_input (int fid)
00752 {
00753 int retval = -1;
00754
00755 #if defined (HAVE_SELECT)
00756 if (fid >= 0)
00757 {
00758 fd_set set;
00759
00760 FD_ZERO (&set);
00761 FD_SET (fid, &set);
00762
00763 retval = gnulib::select (FD_SETSIZE, &set, 0, 0, 0);
00764 }
00765 #else
00766 retval = 1;
00767 #endif
00768
00769 return retval;
00770 }
00771
00772 static octave_value_list
00773 run_command_and_return_output (const std::string& cmd_str)
00774 {
00775 octave_value_list retval;
00776 unwind_protect frame;
00777
00778 iprocstream *cmd = new iprocstream (cmd_str.c_str ());
00779
00780 frame.add_delete (cmd);
00781 frame.add_fcn (octave_child_list::remove, cmd->pid ());
00782
00783 if (*cmd)
00784 {
00785 int fid = cmd->file_number ();
00786
00787 std::ostringstream output_buf;
00788
00789 char ch;
00790
00791 for (;;)
00792 {
00793 if (cmd->get (ch))
00794 output_buf.put (ch);
00795 else
00796 {
00797 if (! cmd->eof () && errno == EAGAIN)
00798 {
00799 cmd->clear ();
00800
00801 if (wait_for_input (fid) != 1)
00802 break;
00803 }
00804 else
00805 break;
00806 }
00807 }
00808
00809 int cmd_status = cmd->close ();
00810
00811 if (WIFEXITED (cmd_status))
00812 cmd_status = WEXITSTATUS (cmd_status);
00813 else
00814 cmd_status = 127;
00815
00816 retval(1) = output_buf.str ();
00817 retval(0) = cmd_status;
00818 }
00819 else
00820 error ("unable to start subprocess for '%s'", cmd_str.c_str ());
00821
00822 return retval;
00823 }
00824
00825 enum system_exec_type { et_sync, et_async };
00826
00827 DEFUN (system, args, nargout,
00828 "-*- texinfo -*-\n\
00829 @deftypefn {Built-in Function} {} system (\"@var{string}\")\n\
00830 @deftypefnx {Built-in Function} {} system (\"@var{string}\", @var{return_output})\n\
00831 @deftypefnx {Built-in Function} {} system (\"@var{string}\", @var{return_output}, @var{type})\n\
00832 @deftypefnx {Built-in Function} {[@var{status}, @var{output}] =} system (@dots{})\n\
00833 Execute a shell command specified by @var{string}.\n\
00834 If the optional argument @var{type} is \"async\", the process\n\
00835 is started in the background and the process ID of the child process\n\
00836 is returned immediately. Otherwise, the child process is started and\n\
00837 Octave waits until it exits. If the @var{type} argument is omitted, it\n\
00838 defaults to the value \"sync\".\n\
00839 \n\
00840 If @var{system} is called with one or more output arguments, or if the\n\
00841 optional argument @var{return_output} is true and the subprocess is started\n\
00842 synchronously, then the output from the command is returned as a variable. \n\
00843 Otherwise, if the subprocess is executed synchronously, its output is sent\n\
00844 to the standard output. To send the output of a command executed with\n\
00845 @code{system} through the pager, use a command like\n\
00846 \n\
00847 @example\n\
00848 @group\n\
00849 [output, text] = system (\"cmd\");\n\
00850 disp (text);\n\
00851 @end group\n\
00852 @end example\n\
00853 \n\
00854 @noindent\n\
00855 or\n\
00856 \n\
00857 @example\n\
00858 printf (\"%s\\n\", nthargout (2, \"system\", \"cmd\"));\n\
00859 @end example\n\
00860 \n\
00861 The @code{system} function can return two values. The first is the\n\
00862 exit status of the command and the second is any output from the\n\
00863 command that was written to the standard output stream. For example,\n\
00864 \n\
00865 @example\n\
00866 [status, output] = system (\"echo foo; exit 2\");\n\
00867 @end example\n\
00868 \n\
00869 @noindent\n\
00870 will set the variable @code{output} to the string @samp{foo}, and the\n\
00871 variable @code{status} to the integer @samp{2}.\n\
00872 \n\
00873 For commands run asynchronously, @var{status} is the process id of the\n\
00874 command shell that is started to run the command.\n\
00875 @seealso{unix, dos}\n\
00876 @end deftypefn")
00877 {
00878 octave_value_list retval;
00879
00880 unwind_protect frame;
00881
00882 int nargin = args.length ();
00883
00884 if (nargin > 0 && nargin < 4)
00885 {
00886 bool return_output = (nargin == 1 && nargout > 1);
00887
00888 system_exec_type type = et_sync;
00889
00890 if (nargin == 3)
00891 {
00892 std::string type_str = args(2).string_value ();
00893
00894 if (! error_state)
00895 {
00896 if (type_str == "sync")
00897 type = et_sync;
00898 else if (type_str == "async")
00899 type = et_async;
00900 else
00901 {
00902 error ("system: TYPE must be \"sync\" or \"async\"");
00903 return retval;
00904 }
00905 }
00906 else
00907 {
00908 error ("system: TYPE must be a character string");
00909 return retval;
00910 }
00911 }
00912
00913 if (nargin > 1)
00914 {
00915 return_output = args(1).is_true ();
00916
00917 if (error_state)
00918 {
00919 error ("system: RETURN_OUTPUT must be boolean value true or false");
00920 return retval;
00921 }
00922 }
00923
00924 if (return_output && type == et_async)
00925 {
00926 error ("system: can't return output from commands run asynchronously");
00927 return retval;
00928 }
00929
00930 std::string cmd_str = args(0).string_value ();
00931
00932 if (! error_state)
00933 {
00934 #if defined (__WIN32__) && ! defined (__CYGWIN__)
00935
00936 if (type == et_sync)
00937 cmd_str = "\"" + cmd_str + "\"";
00938 #endif
00939
00940 if (type == et_async)
00941 {
00942
00943 #ifdef HAVE_FORK
00944 pid_t pid = fork ();
00945
00946 if (pid < 0)
00947 error ("system: fork failed -- can't create child process");
00948 else if (pid == 0)
00949 {
00950
00951
00952
00953 execl ("/bin/sh", "sh", "-c", cmd_str.c_str (),
00954 static_cast<void *> (0));
00955
00956 panic_impossible ();
00957 }
00958 else
00959 retval(0) = pid;
00960 #elif defined (__WIN32__)
00961 STARTUPINFO si;
00962 PROCESS_INFORMATION pi;
00963 ZeroMemory (&si, sizeof (si));
00964 ZeroMemory (&pi, sizeof (pi));
00965 OCTAVE_LOCAL_BUFFER (char, xcmd_str, cmd_str.length()+1);
00966 strcpy (xcmd_str, cmd_str.c_str ());
00967
00968 if (! CreateProcess (0, xcmd_str, 0, 0, FALSE, 0, 0, 0, &si, &pi))
00969 error ("system: CreateProcess failed -- can't create child process");
00970 else
00971 {
00972 retval(0) = pi.dwProcessId;
00973 CloseHandle (pi.hProcess);
00974 CloseHandle (pi.hThread);
00975 }
00976 #else
00977 error ("asynchronous system calls are not supported");
00978 #endif
00979 }
00980 else if (return_output)
00981 retval = run_command_and_return_output (cmd_str);
00982 else
00983 {
00984 int status = system (cmd_str.c_str ());
00985
00986
00987
00988
00989
00990
00991 if (WIFEXITED (status))
00992 status = WEXITSTATUS (status);
00993
00994 retval(0) = status;
00995 }
00996 }
00997 else
00998 error ("system: expecting string as first argument");
00999 }
01000 else
01001 print_usage ();
01002
01003 return retval;
01004 }
01005
01006
01007
01008
01009
01010
01011
01012
01013
01014
01015
01016
01017
01018
01019
01020 std::list<std::string> octave_atexit_functions;
01021
01022 void
01023 do_octave_atexit (void)
01024 {
01025 static bool deja_vu = false;
01026
01027 while (! octave_atexit_functions.empty ())
01028 {
01029 std::string fcn = octave_atexit_functions.front ();
01030
01031 octave_atexit_functions.pop_front ();
01032
01033 OCTAVE_SAFE_CALL (reset_error_handler, ());
01034
01035 OCTAVE_SAFE_CALL (feval, (fcn, octave_value_list (), 0));
01036
01037 OCTAVE_SAFE_CALL (flush_octave_stdout, ());
01038 }
01039
01040 if (! deja_vu)
01041 {
01042 deja_vu = true;
01043
01044
01045
01046
01047 OCTAVE_SAFE_CALL (clear_mex_functions, ());
01048
01049 OCTAVE_SAFE_CALL (command_editor::restore_terminal_state, ());
01050
01051
01052 OCTAVE_SAFE_CALL (raw_mode, (0));
01053
01054 OCTAVE_SAFE_CALL (octave_history_write_timestamp, ());
01055
01056 if (! command_history::ignoring_entries ())
01057 OCTAVE_SAFE_CALL (command_history::clean_up_and_save, ());
01058
01059 OCTAVE_SAFE_CALL (gh_manager::close_all_figures, ());
01060
01061 OCTAVE_SAFE_CALL (gtk_manager::unload_all_toolkits, ());
01062
01063 OCTAVE_SAFE_CALL (close_files, ());
01064
01065 OCTAVE_SAFE_CALL (cleanup_tmp_files, ());
01066
01067 OCTAVE_SAFE_CALL (symbol_table::cleanup, ());
01068
01069 OCTAVE_SAFE_CALL (cleanup_parser, ());
01070
01071 OCTAVE_SAFE_CALL (sysdep_cleanup, ());
01072
01073 OCTAVE_SAFE_CALL (flush_octave_stdout, ());
01074
01075 if (! quitting_gracefully && (interactive || forced_interactive))
01076 {
01077 octave_stdout << "\n";
01078
01079
01080
01081
01082 OCTAVE_SAFE_CALL (flush_octave_stdout, ());
01083 }
01084
01085
01086
01087
01088
01089
01090
01091
01092
01093
01094
01095
01096
01097 OCTAVE_SAFE_CALL (octave_chunk_buffer::clear, ());
01098 }
01099 }
01100
01101 void
01102 octave_add_atexit_function (const std::string& fname)
01103 {
01104 octave_atexit_functions.push_front (fname);
01105 }
01106
01107 bool
01108 octave_remove_atexit_function (const std::string& fname)
01109 {
01110 bool found = false;
01111
01112 for (std::list<std::string>::iterator p = octave_atexit_functions.begin ();
01113 p != octave_atexit_functions.end (); p++)
01114 {
01115 if (*p == fname)
01116 {
01117 octave_atexit_functions.erase (p);
01118 found = true;
01119 break;
01120 }
01121 }
01122
01123 return found;
01124 }
01125
01126
01127 DEFUN (atexit, args, nargout,
01128 "-*- texinfo -*-\n\
01129 @deftypefn {Built-in Function} {} atexit (@var{fcn})\n\
01130 @deftypefnx {Built-in Function} {} atexit (@var{fcn}, @var{flag})\n\
01131 Register a function to be called when Octave exits. For example,\n\
01132 \n\
01133 @example\n\
01134 @group\n\
01135 function last_words ()\n\
01136 disp (\"Bye bye\");\n\
01137 endfunction\n\
01138 atexit (\"last_words\");\n\
01139 @end group\n\
01140 @end example\n\
01141 \n\
01142 @noindent\n\
01143 will print the message \"Bye bye\" when Octave exits.\n\
01144 \n\
01145 The additional argument @var{flag} will register or unregister\n\
01146 @var{fcn} from the list of functions to be called when Octave\n\
01147 exits. If @var{flag} is true, the function is registered, and if\n\
01148 @var{flag} is false, it is unregistered. For example,\n\
01149 after registering the function @code{last_words} above,\n\
01150 \n\
01151 @example\n\
01152 atexit (\"last_words\", false);\n\
01153 @end example\n\
01154 \n\
01155 @noindent\n\
01156 will remove the function from the list and Octave will not call\n\
01157 @code{last_words} when it exits.\n\
01158 \n\
01159 Note that @code{atexit} only removes the first occurrence of a function\n\
01160 from the list, so if a function was placed in the list multiple\n\
01161 times with @code{atexit}, it must also be removed from the list\n\
01162 multiple times.\n\
01163 @end deftypefn")
01164 {
01165 octave_value_list retval;
01166
01167 int nargin = args.length ();
01168
01169 if (nargin == 1 || nargin == 2)
01170 {
01171 std::string arg = args(0).string_value ();
01172
01173 if (! error_state)
01174 {
01175 bool add_mode = true;
01176
01177 if (nargin == 2)
01178 {
01179 add_mode = args(1).bool_value ();
01180
01181 if (error_state)
01182 error ("atexit: FLAG argument must be a logical value");
01183 }
01184
01185 if (! error_state)
01186 {
01187 if (add_mode)
01188 octave_add_atexit_function (arg);
01189 else
01190 {
01191 bool found = octave_remove_atexit_function (arg);
01192
01193 if (nargout > 0)
01194 retval(0) = found;
01195 }
01196 }
01197 }
01198 else
01199 error ("atexit: FCN argument must be a string");
01200 }
01201 else
01202 print_usage ();
01203
01204 return retval;
01205 }
01206
01207 DEFUN (octave_config_info, args, ,
01208 "-*- texinfo -*-\n\
01209 @deftypefn {Built-in Function} {} octave_config_info ()\n\
01210 @deftypefnx {Built-in Function} {} octave_config_info (@var{option})\n\
01211 Return a structure containing configuration and installation\n\
01212 information for Octave.\n\
01213 \n\
01214 If @var{option} is a string, return the configuration information for the\n\
01215 specified option.\n\
01216 \n\
01217 @end deftypefn")
01218 {
01219 octave_value retval;
01220
01221 #if defined (ENABLE_DYNAMIC_LINKING)
01222 bool octave_supports_dynamic_linking = true;
01223 #else
01224 bool octave_supports_dynamic_linking = false;
01225 #endif
01226
01227 static bool initialized = false;
01228 static octave_scalar_map m;
01229
01230 struct conf_info_struct
01231 {
01232 bool subst_home;
01233 const char *key;
01234 const char *val;
01235 };
01236
01237 static const conf_info_struct conf_info[] =
01238 {
01239 { false, "ALL_CFLAGS", OCTAVE_CONF_ALL_CFLAGS },
01240 { false, "ALL_CXXFLAGS", OCTAVE_CONF_ALL_CXXFLAGS },
01241 { false, "ALL_FFLAGS", OCTAVE_CONF_ALL_FFLAGS },
01242 { false, "ALL_LDFLAGS", OCTAVE_CONF_ALL_LDFLAGS },
01243 { false, "AMD_CPPFLAGS", OCTAVE_CONF_AMD_CPPFLAGS },
01244 { false, "AMD_LDFLAGS", OCTAVE_CONF_AMD_LDFLAGS },
01245 { false, "AMD_LIBS", OCTAVE_CONF_AMD_LIBS },
01246 { false, "AR", OCTAVE_CONF_AR },
01247 { false, "ARFLAGS", OCTAVE_CONF_ARFLAGS },
01248 { false, "ARPACK_CPPFLAGS", OCTAVE_CONF_ARPACK_CPPFLAGS },
01249 { false, "ARPACK_LDFLAGS", OCTAVE_CONF_ARPACK_LDFLAGS },
01250 { false, "ARPACK_LIBS", OCTAVE_CONF_ARPACK_LIBS },
01251 { false, "BLAS_LIBS", OCTAVE_CONF_BLAS_LIBS },
01252 { false, "CARBON_LIBS", OCTAVE_CONF_CARBON_LIBS },
01253 { false, "CAMD_CPPFLAGS", OCTAVE_CONF_CAMD_CPPFLAGS },
01254 { false, "CAMD_LDFLAGS", OCTAVE_CONF_CAMD_LDFLAGS },
01255 { false, "CAMD_LIBS", OCTAVE_CONF_CAMD_LIBS },
01256 { false, "CC", OCTAVE_CONF_CC },
01257 { false, "CC_VERSION", OCTAVE_CONF_CC_VERSION },
01258 { false, "CCOLAMD_CPPFLAGS", OCTAVE_CONF_CCOLAMD_CPPFLAGS },
01259 { false, "CCOLAMD_LDFLAGS", OCTAVE_CONF_CCOLAMD_LDFLAGS },
01260 { false, "CCOLAMD_LIBS", OCTAVE_CONF_CCOLAMD_LIBS },
01261 { false, "CFLAGS", OCTAVE_CONF_CFLAGS },
01262 { false, "CHOLMOD_CPPFLAGS", OCTAVE_CONF_CHOLMOD_CPPFLAGS },
01263 { false, "CHOLMOD_LDFLAGS", OCTAVE_CONF_CHOLMOD_LDFLAGS },
01264 { false, "CHOLMOD_LIBS", OCTAVE_CONF_CHOLMOD_LIBS },
01265 { false, "COLAMD_CPPFLAGS", OCTAVE_CONF_COLAMD_CPPFLAGS },
01266 { false, "COLAMD_LDFLAGS", OCTAVE_CONF_COLAMD_LDFLAGS },
01267 { false, "COLAMD_LIBS", OCTAVE_CONF_COLAMD_LIBS },
01268 { false, "CPICFLAG", OCTAVE_CONF_CPICFLAG },
01269 { false, "CPPFLAGS", OCTAVE_CONF_CPPFLAGS },
01270 { false, "CURL_CPPFLAGS", OCTAVE_CONF_CURL_CPPFLAGS },
01271 { false, "CURL_LDFLAGS", OCTAVE_CONF_CURL_LDFLAGS },
01272 { false, "CURL_LIBS", OCTAVE_CONF_CURL_LIBS },
01273 { false, "CXSPARSE_CPPFLAGS", OCTAVE_CONF_CXSPARSE_CPPFLAGS },
01274 { false, "CXSPARSE_LDFLAGS", OCTAVE_CONF_CXSPARSE_LDFLAGS },
01275 { false, "CXSPARSE_LIBS", OCTAVE_CONF_CXSPARSE_LIBS },
01276 { false, "CXX", OCTAVE_CONF_CXX },
01277 { false, "CXXCPP", OCTAVE_CONF_CXXCPP },
01278 { false, "CXXFLAGS", OCTAVE_CONF_CXXFLAGS },
01279 { false, "CXXPICFLAG", OCTAVE_CONF_CXXPICFLAG },
01280 { false, "CXX_VERSION", OCTAVE_CONF_CXX_VERSION },
01281 { false, "DEFAULT_PAGER", OCTAVE_DEFAULT_PAGER },
01282 { false, "DEFS", OCTAVE_CONF_DEFS },
01283 { false, "DL_LD", OCTAVE_CONF_DL_LD },
01284 { false, "DL_LDFLAGS", OCTAVE_CONF_DL_LDFLAGS },
01285 { false, "DL_LIBS", OCTAVE_CONF_DL_LIBS },
01286 { false, "ENABLE_DYNAMIC_LINKING", OCTAVE_CONF_ENABLE_DYNAMIC_LINKING },
01287 { false, "EXEEXT", OCTAVE_CONF_EXEEXT },
01288 { false, "F77", OCTAVE_CONF_F77 },
01289 { false, "F77_FLOAT_STORE_FLAG", OCTAVE_CONF_F77_FLOAT_STORE_FLAG },
01290 { false, "F77_INTEGER_8_FLAG", OCTAVE_CONF_F77_INTEGER_8_FLAG },
01291 { false, "FC", OCTAVE_CONF_FC },
01292 { false, "FFLAGS", OCTAVE_CONF_FFLAGS },
01293 { false, "FFTW3_CPPFLAGS", OCTAVE_CONF_FFTW3_CPPFLAGS },
01294 { false, "FFTW3_LDFLAGS", OCTAVE_CONF_FFTW3_LDFLAGS },
01295 { false, "FFTW3_LIBS", OCTAVE_CONF_FFTW3_LIBS },
01296 { false, "FFTW3F_CPPFLAGS", OCTAVE_CONF_FFTW3F_CPPFLAGS },
01297 { false, "FFTW3F_LDFLAGS", OCTAVE_CONF_FFTW3F_LDFLAGS },
01298 { false, "FFTW3F_LIBS", OCTAVE_CONF_FFTW3F_LIBS },
01299 { false, "FLIBS", OCTAVE_CONF_FLIBS },
01300 { false, "FPICFLAG", OCTAVE_CONF_FPICFLAG },
01301 { false, "FT2_LIBS", OCTAVE_CONF_FT2_LIBS },
01302 { false, "GLPK_CPPFLAGS", OCTAVE_CONF_GLPK_CPPFLAGS },
01303 { false, "GLPK_LDFLAGS", OCTAVE_CONF_GLPK_LDFLAGS },
01304 { false, "GLPK_LIBS", OCTAVE_CONF_GLPK_LIBS },
01305 { false, "GNUPLOT", OCTAVE_CONF_GNUPLOT },
01306 { false, "GRAPHICS_LIBS", OCTAVE_CONF_GRAPHICS_LIBS },
01307 { false, "HDF5_CPPFLAGS", OCTAVE_CONF_HDF5_CPPFLAGS },
01308 { false, "HDF5_LDFLAGS", OCTAVE_CONF_HDF5_LDFLAGS },
01309 { false, "HDF5_LIBS", OCTAVE_CONF_HDF5_LIBS },
01310 { false, "INCFLAGS", OCTAVE_CONF_INCFLAGS },
01311 { false, "LAPACK_LIBS", OCTAVE_CONF_LAPACK_LIBS },
01312 { false, "LDFLAGS", OCTAVE_CONF_LDFLAGS },
01313 { false, "LD_CXX", OCTAVE_CONF_LD_CXX },
01314 { false, "LD_STATIC_FLAG", OCTAVE_CONF_LD_STATIC_FLAG },
01315 { false, "LEX", OCTAVE_CONF_LEX },
01316 { false, "LEXLIB", OCTAVE_CONF_LEXLIB },
01317 { false, "LFLAGS", OCTAVE_CONF_LFLAGS },
01318 { false, "LIBCRUFT", OCTAVE_CONF_LIBCRUFT },
01319 { false, "LIBEXT", OCTAVE_CONF_LIBEXT },
01320 { false, "LIBFLAGS", OCTAVE_CONF_LIBFLAGS },
01321 { false, "LIBOCTAVE", OCTAVE_CONF_LIBOCTAVE },
01322 { false, "LIBOCTINTERP", OCTAVE_CONF_LIBOCTINTERP },
01323 { false, "LIBS", OCTAVE_CONF_LIBS },
01324 { false, "LN_S", OCTAVE_CONF_LN_S },
01325 { false, "MAGICK_CPPFLAGS", OCTAVE_CONF_MAGICK_CPPFLAGS },
01326 { false, "MAGICK_LDFLAGS", OCTAVE_CONF_MAGICK_LDFLAGS },
01327 { false, "MAGICK_LIBS", OCTAVE_CONF_MAGICK_LIBS },
01328 { false, "MKOCTFILE_DL_LDFLAGS", OCTAVE_CONF_MKOCTFILE_DL_LDFLAGS },
01329 { false, "OCTAVE_LINK_DEPS", OCTAVE_CONF_OCTAVE_LINK_DEPS },
01330 { false, "OCTAVE_LINK_OPTS", OCTAVE_CONF_OCTAVE_LINK_OPTS },
01331 { false, "OCT_LINK_DEPS", OCTAVE_CONF_OCT_LINK_DEPS },
01332 { false, "OCT_LINK_OPTS", OCTAVE_CONF_OCT_LINK_OPTS },
01333 { false, "OPENGL_LIBS", OCTAVE_CONF_OPENGL_LIBS },
01334 { false, "PTHREAD_CFLAGS", OCTAVE_CONF_PTHREAD_CFLAGS },
01335 { false, "PTHREAD_LIBS", OCTAVE_CONF_PTHREAD_LIBS },
01336 { false, "QHULL_CPPFLAGS", OCTAVE_CONF_QHULL_CPPFLAGS },
01337 { false, "QHULL_LDFLAGS", OCTAVE_CONF_QHULL_LDFLAGS },
01338 { false, "QHULL_LIBS", OCTAVE_CONF_QHULL_LIBS },
01339 { false, "QRUPDATE_CPPFLAGS", OCTAVE_CONF_QRUPDATE_CPPFLAGS },
01340 { false, "QRUPDATE_LDFLAGS", OCTAVE_CONF_QRUPDATE_LDFLAGS },
01341 { false, "QRUPDATE_LIBS", OCTAVE_CONF_QRUPDATE_LIBS },
01342 { false, "RANLIB", OCTAVE_CONF_RANLIB },
01343 { false, "RDYNAMIC_FLAG", OCTAVE_CONF_RDYNAMIC_FLAG },
01344 { false, "READLINE_LIBS", OCTAVE_CONF_READLINE_LIBS },
01345 { false, "REGEX_LIBS", OCTAVE_CONF_REGEX_LIBS },
01346 { false, "SED", OCTAVE_CONF_SED },
01347 { false, "SHARED_LIBS", OCTAVE_CONF_SHARED_LIBS },
01348 { false, "SHLEXT", OCTAVE_CONF_SHLEXT },
01349 { false, "SHLEXT_VER", OCTAVE_CONF_SHLEXT_VER },
01350 { false, "SH_LD", OCTAVE_CONF_SH_LD },
01351 { false, "SH_LDFLAGS", OCTAVE_CONF_SH_LDFLAGS },
01352 { false, "SONAME_FLAGS", OCTAVE_CONF_SONAME_FLAGS },
01353 { false, "STATIC_LIBS", OCTAVE_CONF_STATIC_LIBS },
01354 { false, "TERM_LIBS", OCTAVE_CONF_TERM_LIBS },
01355 { false, "UGLY_DEFS", OCTAVE_CONF_UGLY_DEFS },
01356 { false, "UMFPACK_CPPFLAGS", OCTAVE_CONF_UMFPACK_CPPFLAGS },
01357 { false, "UMFPACK_LDFLAGS", OCTAVE_CONF_UMFPACK_LDFLAGS },
01358 { false, "UMFPACK_LIBS", OCTAVE_CONF_UMFPACK_LIBS },
01359 { false, "USE_64_BIT_IDX_T", OCTAVE_CONF_USE_64_BIT_IDX_T },
01360 { false, "X11_INCFLAGS", OCTAVE_CONF_X11_INCFLAGS },
01361 { false, "X11_LIBS", OCTAVE_CONF_X11_LIBS },
01362 { false, "XTRA_CFLAGS", OCTAVE_CONF_XTRA_CFLAGS },
01363 { false, "XTRA_CXXFLAGS", OCTAVE_CONF_XTRA_CXXFLAGS },
01364 { false, "YACC", OCTAVE_CONF_YACC },
01365 { false, "YFLAGS", OCTAVE_CONF_YFLAGS },
01366 { false, "Z_CPPFLAGS", OCTAVE_CONF_Z_CPPFLAGS },
01367 { false, "Z_LDFLAGS", OCTAVE_CONF_Z_LDFLAGS },
01368 { false, "Z_LIBS", OCTAVE_CONF_Z_LIBS },
01369 { false, "api_version", OCTAVE_API_VERSION },
01370 { true, "archlibdir", OCTAVE_ARCHLIBDIR },
01371 { true, "bindir", OCTAVE_BINDIR },
01372 { false, "canonical_host_type", OCTAVE_CANONICAL_HOST_TYPE },
01373 { false, "config_opts", OCTAVE_CONF_config_opts },
01374 { true, "datadir", OCTAVE_DATADIR },
01375 { true, "datarootdir", OCTAVE_DATAROOTDIR },
01376 { true, "exec_prefix", OCTAVE_EXEC_PREFIX },
01377 { true, "fcnfiledir", OCTAVE_FCNFILEDIR },
01378 { true, "imagedir", OCTAVE_IMAGEDIR },
01379 { true, "includedir", OCTAVE_INCLUDEDIR },
01380 { true, "infodir", OCTAVE_INFODIR },
01381 { true, "infofile", OCTAVE_INFOFILE },
01382 { true, "libdir", OCTAVE_LIBDIR },
01383 { true, "libexecdir", OCTAVE_LIBEXECDIR },
01384 { true, "localapiarchlibdir", OCTAVE_LOCALAPIARCHLIBDIR },
01385 { true, "localapifcnfiledir", OCTAVE_LOCALAPIFCNFILEDIR },
01386 { true, "localapioctfiledir", OCTAVE_LOCALAPIOCTFILEDIR },
01387 { true, "localarchlibdir", OCTAVE_LOCALARCHLIBDIR },
01388 { true, "localfcnfiledir", OCTAVE_LOCALFCNFILEDIR },
01389 { true, "localoctfiledir", OCTAVE_LOCALOCTFILEDIR },
01390 { true, "localstartupfiledir", OCTAVE_LOCALSTARTUPFILEDIR },
01391 { true, "localverarchlibdir", OCTAVE_LOCALVERARCHLIBDIR },
01392 { true, "localverfcnfiledir", OCTAVE_LOCALVERFCNFILEDIR },
01393 { true, "localveroctfiledir", OCTAVE_LOCALVEROCTFILEDIR },
01394 { true, "man1dir", OCTAVE_MAN1DIR },
01395 { false, "man1ext", OCTAVE_MAN1EXT },
01396 { true, "mandir", OCTAVE_MANDIR },
01397 { true, "octfiledir", OCTAVE_OCTFILEDIR },
01398 { true, "octetcdir", OCTAVE_OCTETCDIR },
01399 { true, "octincludedir", OCTAVE_OCTINCLUDEDIR },
01400 { true, "octlibdir", OCTAVE_OCTLIBDIR },
01401 { true, "prefix", OCTAVE_PREFIX },
01402 { true, "startupfiledir", OCTAVE_STARTUPFILEDIR },
01403 { false, "version", OCTAVE_VERSION },
01404 { false, 0, 0 }
01405 };
01406
01407 if (! initialized)
01408 {
01409 m.assign ("dld", octave_value (octave_supports_dynamic_linking));
01410
01411 oct_mach_info::float_format ff = oct_mach_info::native_float_format ();
01412 m.assign ("float_format",
01413 octave_value (oct_mach_info::float_format_as_string (ff)));
01414
01415 m.assign ("words_big_endian",
01416 octave_value (oct_mach_info::words_big_endian ()));
01417
01418 m.assign ("words_little_endian",
01419 octave_value (oct_mach_info::words_little_endian ()));
01420
01421 int i = 0;
01422
01423 while (true)
01424 {
01425 const conf_info_struct& elt = conf_info[i++];
01426
01427 const char *key = elt.key;
01428
01429 if (key)
01430 {
01431 if (elt.subst_home)
01432 m.assign (key, subst_octave_home (elt.val));
01433 else
01434 m.assign (key, elt.val);
01435 }
01436 else
01437 break;
01438 }
01439
01440 bool unix_system = true;
01441 bool mac_system = false;
01442 bool windows_system = false;
01443
01444 #if defined (WIN32)
01445 windows_system = true;
01446 #if !defined (__CYGWIN__)
01447 unix_system = false;
01448 #endif
01449 #endif
01450
01451 #if defined (OCTAVE_USE_OS_X_API)
01452 mac_system = true;
01453 #endif
01454
01455 m.assign ("unix", octave_value (unix_system));
01456 m.assign ("mac", octave_value (mac_system));
01457 m.assign ("windows", octave_value (windows_system));
01458
01459 initialized = true;
01460 }
01461
01462 int nargin = args.length ();
01463
01464 if (nargin == 1)
01465 {
01466 std::string arg = args(0).string_value ();
01467
01468 if (! error_state)
01469 {
01470 Cell c = m.contents (arg.c_str ());
01471
01472 if (c.is_empty ())
01473 error ("octave_config_info: no info for '%s'", arg.c_str ());
01474 else
01475 retval = c(0);
01476 }
01477 }
01478 else if (nargin == 0)
01479 retval = m;
01480 else
01481 print_usage ();
01482
01483 return retval;
01484 }
01485
01486
01487
01488
01489
01490
01491
01492
01493
01494
01495 #if defined (__GNUG__) && defined (DEBUG_NEW_DELETE)
01496
01497 int debug_new_delete = 0;
01498
01499 typedef void (*vfp)(void);
01500 extern vfp __new_handler;
01501
01502 void *
01503 __builtin_new (size_t sz)
01504 {
01505 void *p;
01506
01507
01508 if (sz == 0)
01509 sz = 1;
01510 p = malloc (sz);
01511 while (p == 0)
01512 {
01513 (*__new_handler) ();
01514 p = malloc (sz);
01515 }
01516
01517 if (debug_new_delete)
01518 std::cerr << "__builtin_new: " << p << std::endl;
01519
01520 return p;
01521 }
01522
01523 void
01524 __builtin_delete (void *ptr)
01525 {
01526 if (debug_new_delete)
01527 std::cerr << "__builtin_delete: " << ptr << std::endl;
01528
01529 if (ptr)
01530 free (ptr);
01531 }
01532
01533 #endif