toplev.cc

Go to the documentation of this file.
00001 /*
00002 
00003 Copyright (C) 1995-2012 John W. Eaton
00004 
00005 This file is part of Octave.
00006 
00007 Octave is free software; you can redistribute it and/or modify it
00008 under the terms of the GNU General Public License as published by the
00009 Free Software Foundation; either version 3 of the License, or (at your
00010 option) any later version.
00011 
00012 Octave is distributed in the hope that it will be useful, but WITHOUT
00013 ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
00014 FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
00015 for more details.
00016 
00017 You should have received a copy of the GNU General Public License
00018 along with Octave; see the file COPYING.  If not, see
00019 <http://www.gnu.org/licenses/>.
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 // TRUE means the quit() call is allowed.
00083 bool quit_allowed = true;
00084 
00085 // TRUE means we are exiting via the builtin exit or quit functions.
00086 bool quitting_gracefully = false;
00087 // This stores the exit status.
00088 int exit_status = 0;
00089 
00090 // TRUE means we are ready to interpret commands, but not everything
00091 // is ready for interactive use.
00092 bool octave_interpreter_ready = false;
00093 
00094 // TRUE means we've processed all the init code and we are good to go.
00095 bool octave_initialized = false;
00096 
00097 // Current command to execute.
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   // Look for the caller of dbstack.
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   // We counted how many user frames were not the one, in reverse.
00218   // Now set curr_user_frame to be the index in the other direction.
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 // Use static fields for the best efficiency.
00253 // NOTE: C++0x will allow these two to be merged into one.
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   // Our list is reversed.
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   // Start looking with the caller of dbup/dbdown/keyboard.
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       // There is no need to set scope and context here.  That will
00436       // happen when the dbup/dbdown/keyboard frame is popped and we
00437       // jump to the new "prev" frame set above.
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             // We found the current user code frame, so skip it.
00462             skipped = true;
00463           else
00464             {
00465               // We found the caller user code frame.
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   // The big loop.
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           // Do this with an unwind-protect cleanup function so that
00573           // the forced variables will be unmarked in the event of an
00574           // interrupt.
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           // This is the same as yyparse in parse.y.
00583           retval = octave_parse ();
00584 
00585           if (retval == 0)
00586             {
00587               if (global_command)
00588                 {
00589                   // Use an unwind-protect cleanup function so that the
00590                   // global_command list will be deleted in the event of
00591                   // an interrupt.
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                           // We should exit with a non-zero status.
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; // If user has overriden the exit func.
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 // Fix up things before exiting.
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           // Instead of simply calling exit, we simulate an interrupt
00702           // with a request to exit cleanly so that no matter where the
00703           // call to quit occurs, we will run the unwind_protect stack,
00704           // clear the OCTAVE_LOCAL_BUFFER allocations, etc. before
00705           // exiting.
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 // Execute a shell command.
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           // Work around weird double-quote handling on Windows systems.
00936           if (type == et_sync)
00937             cmd_str = "\"" + cmd_str + "\"";
00938 #endif
00939 
00940           if (type == et_async)
00941             {
00942               // FIXME -- maybe this should go in sysdep.cc?
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                   // FIXME -- should probably replace this
00951                   // call with something portable.
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               // The value in status is as returned by waitpid.  If
00987               // the process exited normally, extract the actual exit
00988               // status of the command.  Otherwise, return 127 as a
00989               // failure code.
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 %!test
01008 %! cmd = ls_command ();
01009 %! [status, output] = system (cmd);
01010 %! assert (status, 0);
01011 %! assert (ischar (output));
01012 %! assert (! isempty (output));
01013 
01014 %!error system ()
01015 %!error system (1, 2, 3)
01016 */
01017 
01018 // FIXME -- this should really be static, but that causes
01019 // problems on some systems.
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       // Do this explicitly so that destructors for mex file objects
01045       // are called, so that functions registered with mexAtExit are
01046       // called.
01047       OCTAVE_SAFE_CALL (clear_mex_functions, ());
01048 
01049       OCTAVE_SAFE_CALL (command_editor::restore_terminal_state, ());
01050 
01051       // FIXME -- is this needed?  Can it cause any trouble?
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           // Yes, we want this to be separate from the call to
01080           // flush_octave_stdout above.
01081 
01082           OCTAVE_SAFE_CALL (flush_octave_stdout, ());
01083         }
01084 
01085       // Don't call singleton_cleanup_list::cleanup until we have the
01086       // problems with registering/unregistering types worked out.  For
01087       // example, uncomment the following line, then use the make_int
01088       // function from the examples directory to create an integer
01089       // object and then exit Octave.  Octave should crash with a
01090       // segfault when cleaning up the typinfo singleton.  We need some
01091       // way to force new octave_value_X types that are created in
01092       // .oct files to be unregistered when the .oct file shared library
01093       // is unloaded.
01094       //
01095       // OCTAVE_SAFE_CALL (singleton_cleanup_list::cleanup, ());
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 %!error octave_config_info (1, 2);
01488 %!assert (ischar (octave_config_info ("version")));
01489 %!test
01490 %! x = octave_config_info ();
01491 %! assert (isstruct (x));
01492 %! assert (! isempty (x));
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   /* malloc (0) is unpredictable; avoid it.  */
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
 All Classes Files Functions Variables Typedefs Enumerations Enumerator Friends Defines