home *** CD-ROM | disk | FTP | other *** search
/ Geek Gadgets 1 / ADE-1.bin / ade-dist / octave-1.1.1p1-base.tgz / octave-1.1.1p1-base.tar / fsf / octave / src / octave.cc < prev    next >
C/C++ Source or Header  |  1996-09-27  |  21KB  |  963 lines

  1. // octave.cc                                            -*- C++ -*-
  2. /*
  3.  
  4. Copyright (C) 1992, 1993, 1994, 1995 John W. Eaton
  5.  
  6. This file is part of Octave.
  7.  
  8. Octave is free software; you can redistribute it and/or modify it
  9. under the terms of the GNU General Public License as published by the
  10. Free Software Foundation; either version 2, or (at your option) any
  11. later version.
  12.  
  13. Octave is distributed in the hope that it will be useful, but WITHOUT
  14. ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
  15. FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
  16. for more details.
  17.  
  18. You should have received a copy of the GNU General Public License
  19. along with Octave; see the file COPYING.  If not, write to the Free
  20. Software Foundation, 675 Mass Ave, Cambridge, MA 02139, USA.
  21.  
  22. */
  23.  
  24. // Born February 20, 1992.
  25.  
  26. #ifdef HAVE_CONFIG_H
  27. #include "config.h"
  28. #endif
  29.  
  30. #include <sys/types.h>
  31. #ifdef HAVE_UNISTD_H
  32. #include <unistd.h>
  33. #endif
  34. #include <sys/stat.h>
  35. #include <time.h>
  36. #include <pwd.h>
  37. #include <stdlib.h>
  38. #include <string.h>
  39. #include <signal.h>
  40. #include <assert.h>
  41. #include <iostream.h>
  42. #include <strstream.h>
  43. #include <fstream.h>
  44.  
  45. extern "C"
  46. {
  47. #include <setjmp.h>
  48. }
  49.  
  50. #include "getopt.h"
  51.  
  52. #include "lo-error.h"
  53.  
  54. #include "sighandlers.h"
  55. #include "variables.h"
  56. #include "error.h"
  57. #include "dynamic-ld.h"
  58. #include "tree-misc.h"
  59. #include "tree-const.h"
  60. #include "tree-plot.h"
  61. #include "utils.h"
  62. #include "input.h"
  63. #include "pager.h"
  64. #include "lex.h"
  65. #include "help.h"
  66. #include "octave.h"
  67. #include "parse.h"
  68. #include "defaults.h"
  69. #include "user-prefs.h"
  70. #include "procstream.h"
  71. #include "unwind-prot.h"
  72. #include "octave-hist.h"
  73. #include "builtins.h"
  74. #include "version.h"
  75. #include "file-io.h"
  76. #include "sysdep.h"
  77. #include "defun.h"
  78.  
  79. #if !defined (HAVE_ATEXIT) && defined (HAVE_ON_EXIT)
  80. extern "C" { int on_exit (); }
  81. #define atexit on_exit
  82. #endif
  83.  
  84. // argv[0] for this program.
  85. char *raw_prog_name = 0;
  86.  
  87. // Cleaned-up name of this program, not including path information.
  88. char *prog_name = 0;
  89.  
  90. // Login name for user running this program.
  91. char *user_name = 0;
  92.  
  93. // Name of the host we are running on.
  94. char *host_name = 0;
  95.  
  96. // User's home directory.
  97. char *home_directory = 0;
  98.  
  99. // Guess what?
  100. char *the_current_working_directory = 0;
  101.  
  102. // Load path specified on command line.  (--path path; -p path)
  103. char *load_path = 0;
  104.  
  105. // Name of the info file specified on command line.
  106. // (--info-file file; -i file)
  107. char *info_file = 0;
  108.  
  109. // Name of the editor to be invoked by the edit_history command.
  110. char *editor = 0;
  111.  
  112. // If nonzero, don't do fancy line editing.
  113. int no_line_editing = 0;
  114.  
  115. // If nonzero, print verbose info in some cases.
  116. // (--verbose; -V)
  117. int verbose_flag = 0;
  118.  
  119. // Command number, counting from the beginning of this session.
  120. int current_command_number = 1;
  121.  
  122. // Nonzero means we are exiting via the builtin exit or quit functions.
  123. int quitting_gracefully = 0;
  124.  
  125. // Current command to execute.
  126. tree_statement_list *global_command = 0;
  127.  
  128. // Pointer to function that is currently being evaluated.
  129. tree_function *curr_function = 0;
  130.  
  131. // Nonzero means input is coming from startup file.
  132. int input_from_startup_file = 0;
  133.  
  134. // Top level context (?)
  135. jmp_buf toplevel;
  136.  
  137. // This is from readline's paren.c:
  138. extern int rl_blink_matching_paren;
  139.  
  140. // Nonzero means we read ~/.octaverc and ./.octaverc.
  141. // (--norc; --ignore-init-file; -f)
  142. static int read_init_files = 1;
  143.  
  144. // Nonzero means we printed messages about reading startup files.
  145. static int reading_startup_message_printed = 0;
  146.  
  147. // Nonzero means we don\'t print the usual startup message.
  148. // (--quiet; --silent; -q)
  149. static int inhibit_startup_message = 0;
  150.  
  151. // Usage message
  152. static const char *usage_string = 
  153.   "octave [-?Vdfhiqvx] [-p path] [--debug] [--help] [--ignore-init-file]\n\
  154.        [--info-file file] [--interactive] [--path path] [--silent]\n\
  155.        [--verbose] [--version] [--echo-commands] [file]";
  156.  
  157. // This is here so that it\'s more likely that the usage message and
  158. // the real set of options will agree.
  159. static const char *short_opts = "?Vdfhip:qvx";
  160.  
  161. // Long options.  See the comments in getopt.h for the meanings of the
  162. // fields in this structure.
  163. #define INFO_FILE_OPTION 1
  164. static struct option long_opts[] =
  165.   {
  166.     { "debug",            no_argument,       0, 'd' },
  167.     { "help",             no_argument,       0, 'h' },
  168.     { "interactive",      no_argument,       0, 'i' },
  169.     { "info-file",        required_argument, 0, INFO_FILE_OPTION },
  170.     { "norc",             no_argument,       0, 'f' },
  171.     { "ignore-init-file", no_argument,       0, 'f' },
  172.     { "path",             required_argument, 0, 'p' },
  173.     { "quiet",            no_argument,       0, 'q' },
  174.     { "silent",           no_argument,       0, 'q' },
  175.     { "verbose",          no_argument,       0, 'V' },
  176.     { "version",          no_argument,       0, 'v' },
  177.     { "echo-commands",    no_argument,       0, 'x' },
  178.     { 0,                  0,                 0, 0 }
  179.   };
  180.  
  181. // Initialize some global variables for later use.
  182.  
  183. static void
  184. initialize_globals (char *name)
  185. {
  186.   struct passwd *entry = getpwuid (getuid ());
  187.   if (entry)
  188.     user_name = strsave (entry->pw_name);
  189.   else
  190.     user_name = strsave ("I have no name!");
  191.   endpwent ();
  192.  
  193.   char hostname[256];
  194.   if (gethostname (hostname, 255) < 0)
  195.     host_name = strsave ("I have no host!");
  196.   else
  197.     host_name = strsave (hostname);
  198.  
  199.   char *hd = getenv ("HOME");
  200.   if (hd)
  201.     home_directory = strsave (hd);
  202.   else
  203.     home_directory = strsave ("I have no home!");
  204.  
  205.   char *shell_path = getenv ("PATH");
  206.   char *arch_dir = octave_arch_lib_dir ();
  207.   char *bin_dir = octave_bin_dir ();
  208.  
  209.   int len = strlen (arch_dir) + strlen (bin_dir) + 7;
  210.  
  211.   char *putenv_cmd = 0;
  212.  
  213.   if (shell_path)
  214.     {
  215.       len += strlen (shell_path) + 1;
  216.       putenv_cmd = new char [len];
  217.       sprintf (putenv_cmd,
  218.            "PATH=%s" SEPCHAR_STR "%s" SEPCHAR_STR "%s",
  219.            shell_path, arch_dir, bin_dir);
  220.     }
  221.   else
  222.     {
  223.       putenv_cmd = new char [len];
  224.       sprintf (putenv_cmd, "PATH=%s" SEPCHAR_STR "%s", arch_dir, bin_dir);
  225.     }
  226.  
  227.   putenv (putenv_cmd);
  228.  
  229.   raw_prog_name = strsave (name);
  230.   prog_name = strsave ("octave");
  231.  
  232.   load_path = default_path ();
  233.  
  234.   info_file = default_info_file ();
  235.  
  236.   editor = default_editor ();
  237. }
  238.  
  239. void
  240. parse_and_execute (FILE *f, int print)
  241. {
  242.   begin_unwind_frame ("parse_and_execute");
  243.   
  244.   YY_BUFFER_STATE old_buf = current_buffer ();
  245.   YY_BUFFER_STATE new_buf = create_buffer (f);
  246.  
  247.   add_unwind_protect (restore_input_buffer, (void *) old_buf);
  248.   add_unwind_protect (delete_input_buffer, (void *) new_buf);
  249.  
  250.   switch_to_buffer (new_buf);
  251.  
  252.   unwind_protect_int (echo_input);
  253.   unwind_protect_int (using_readline);
  254.   unwind_protect_int (saving_history);
  255.  
  256.   echo_input = 0;
  257.   using_readline = 0;
  258.   saving_history = 0;
  259.  
  260.   unwind_protect_ptr (curr_sym_tab);
  261.  
  262.   int retval;
  263.   do
  264.     {
  265.       reset_parser ();
  266.  
  267.       retval = yyparse ();
  268.  
  269.       if (retval == 0 && global_command)
  270.     {
  271.       global_command->eval (print);
  272.       delete global_command;
  273.     }
  274.     }
  275.   while (retval == 0);
  276.  
  277.   run_unwind_frame ("parse_and_execute");
  278. }
  279.  
  280. void
  281. parse_and_execute (char *s, int print, int verbose)
  282. {
  283.   begin_unwind_frame ("parse_and_execute_2");
  284.  
  285.   unwind_protect_int (reading_script_file);
  286.  
  287.   reading_script_file = 1;
  288.  
  289.   FILE *f = get_input_from_file (s, 0);
  290.   if (f)
  291.     {
  292.       unwind_protect_int (input_line_number);
  293.       unwind_protect_int (current_input_column);
  294.       unwind_protect_int (echo_input);
  295.  
  296.       input_line_number = 0;
  297.       current_input_column = 1;
  298.       echo_input = 0;
  299.  
  300.       if (verbose)
  301.     {
  302.       cout << "reading commands from " << s << " ... ";
  303.       reading_startup_message_printed = 1;
  304.       cout.flush ();
  305.     }
  306.  
  307.       parse_and_execute (f, print);
  308.  
  309.       fclose (f);
  310.  
  311.       if (verbose)
  312.     cout << "done." << endl;
  313.     }
  314.  
  315.   run_unwind_frame ("parse_and_execute_2");
  316. }
  317.  
  318. // Initialize by reading startup files.
  319.  
  320. static void
  321. execute_startup_files (void)
  322. {
  323.   begin_unwind_frame ("execute_startup_files");
  324.  
  325.   unwind_protect_int (input_from_startup_file);
  326.   input_from_startup_file = 1;
  327.  
  328.   int verbose = (verbose_flag && ! inhibit_startup_message);
  329.  
  330. // Execute commands from the site-wide configuration file.
  331.  
  332.   char *sd = get_site_defaults ();
  333.  
  334.   parse_and_execute (sd, 0, verbose);
  335.  
  336. // Try to execute commands from $HOME/.octaverc and ./.octaverc.
  337.  
  338.   char *home_rc = 0;
  339.   if (home_directory)
  340.     {
  341.       home_rc = strconcat (home_directory, "/.octaverc");
  342.       parse_and_execute (home_rc, 0, verbose);
  343.     }
  344.  
  345. // Names alone are not enough.
  346.  
  347.   struct stat home_rc_statbuf;
  348.   stat (home_rc, &home_rc_statbuf);
  349.   delete [] home_rc;
  350.  
  351.   struct stat dot_rc_statbuf;
  352.   stat ("./.octaverc", &dot_rc_statbuf);
  353.  
  354.   if (home_rc_statbuf.st_ino != dot_rc_statbuf.st_ino)
  355.     parse_and_execute ("./.octaverc", 0, verbose);
  356.  
  357.   run_unwind_frame ("execute_startup_files");
  358. }
  359.  
  360. // Usage message with extra help.
  361.  
  362. static void
  363. verbose_usage (void)
  364. {
  365.   cout << "\n" OCTAVE_NAME_VERSION_AND_COPYRIGHT "\n\n\
  366. Usage: " << usage_string << "\n\
  367. \n\
  368.   -d, --debug             enter parser debugging mode\n\
  369.   -f, --ignore-init-file  don't read any initialization files\n\
  370.   -h, -?, --help          print short help message and exit\n\
  371.   -i, --interactive       force interactive behavior\n\
  372.   --info-file FILE        use top-level info file FILE\n\
  373.   -p PATH, --path PATH    set initial LOADPATH to PATH\n\
  374.   -q, --silent            don't print message at startup\n\
  375.   -V, --verbose           enable verbose output in some cases\n\
  376.   -v, --version           print version number and exit\n\
  377.   -x, --echo-commands     echo commands as they are executed\n\
  378. \n\
  379.   FILE                    execute commands from FILE\n\
  380. \n";
  381.  
  382.   exit (0);
  383. }
  384.  
  385. // Terse usage messsage.
  386.  
  387. static void
  388. usage (void)
  389. {
  390.   cerr << "usage: " << usage_string << "\n";
  391.   exit (1);
  392. }
  393.  
  394. // Fix up things before exiting.
  395.  
  396. void
  397. clean_up_and_exit (int retval)
  398. {
  399.   raw_mode (0);
  400.  
  401.   clean_up_history ();
  402.  
  403.   close_plot_stream ();
  404.  
  405.   close_diary_file ();
  406.  
  407.   close_files ();
  408.  
  409.   cleanup_tmp_files ();
  410.  
  411.   if (!quitting_gracefully && (interactive || forced_interactive))
  412.     cout << "\n";
  413.  
  414.   if (retval == EOF)
  415.     retval = 0;
  416.  
  417.   exit (retval);
  418.  
  419. // This is bogus but should prevent g++ from giving a warning saying
  420. // that this volatile function does return.
  421.  
  422.   panic_impossible ();
  423. }
  424.  
  425. static void
  426. print_version_and_exit (void)
  427. {
  428.   cout << OCTAVE_NAME_AND_VERSION << "\n";
  429.   exit (0);
  430. }
  431.  
  432. static void
  433. initialize_error_handlers ()
  434. {
  435.   set_liboctave_error_handler (error);
  436. }
  437.  
  438. // You guessed it.
  439.  
  440. int
  441. main (int argc, char **argv)
  442. {
  443. // The order of these calls is important, and initialize globals must
  444. // come before the options are processed because some command line
  445. // options override defaults.
  446.  
  447.   init_user_prefs ();
  448.  
  449.   initialize_pager ();
  450.  
  451.   sysdep_init ();
  452.  
  453.   initialize_error_handlers ();
  454.  
  455.   initialize_globals (argv[0]);
  456.  
  457.   int optc;
  458.   while ((optc = getopt_long (argc, argv, short_opts, long_opts, 0)) != EOF)
  459.     {
  460.       switch (optc)
  461.     {
  462.     case 'V':
  463.       verbose_flag++;
  464.       break;
  465.  
  466.     case 'd':
  467.       yydebug++;
  468.       break;
  469.  
  470.     case 'f':
  471.       read_init_files = 0;
  472.       break;
  473.  
  474.     case 'h':
  475.     case '?':
  476.       verbose_usage ();
  477.       break;
  478.  
  479.     case 'i':
  480.       forced_interactive = 1;
  481.       break;
  482.  
  483.     case 'p':
  484.       if (optarg)
  485.         load_path = strsave (optarg);
  486.       break;
  487.  
  488.     case 'q':
  489.       inhibit_startup_message = 1;
  490.       break;
  491.  
  492.     case 'x':
  493.       echo_input = 1;
  494.       break;
  495.  
  496.     case 'v':
  497.       print_version_and_exit ();
  498.       break;
  499.  
  500.     case INFO_FILE_OPTION:
  501.       if (optarg)
  502.         info_file = strsave (optarg);
  503.       break;
  504.  
  505.     default:
  506.       usage ();
  507.       break;
  508.     }
  509.     }
  510.  
  511. #if defined (HAVE_ATEXIT) || (HAVE_ON_EXIT)
  512. // Make sure we clean up when we exit.  If we don't have atexit or
  513. // on_exit, we're going to leave some junk files around if we exit
  514. // abnormally.
  515.   atexit (cleanup_tmp_files);
  516. #endif
  517.  
  518. // These can come after command line args since none of them set any
  519. // defaults that might be changed by command line options.
  520.  
  521.   install_signal_handlers ();
  522.  
  523.   initialize_history ();
  524.  
  525.   initialize_file_io ();
  526.  
  527.   initialize_symbol_tables ();  
  528.  
  529.   install_builtins ();
  530.  
  531.   initialize_readline ();
  532.  
  533.   init_dynamic_linker ();
  534.  
  535.   if (! inhibit_startup_message)
  536.     cout << OCTAVE_STARTUP_MESSAGE "\n" << endl;
  537.  
  538.   if (read_init_files)
  539.     {
  540.       saving_history = 0;
  541.       execute_startup_files ();
  542.       saving_history = 1;
  543.     }
  544.  
  545.   if (! inhibit_startup_message && reading_startup_message_printed)
  546.     cout << endl;
  547.  
  548. // Avoid counting commands executed from startup files.
  549.   current_command_number = 1;
  550.  
  551. // If there is an extra argument, see if it names a file to read.
  552.  
  553.   int remaining_args = argc - optind;
  554.   if (remaining_args > 1)
  555.     {
  556.       usage ();
  557.     }
  558.   else if (remaining_args == 1)
  559.     {
  560.       reading_script_file = 1;
  561.       curr_fcn_file_name = argv[optind];
  562.       FILE *infile = get_input_from_file (curr_fcn_file_name);
  563.       if (infile)
  564.     {
  565.       rl_blink_matching_paren = 0;
  566.       switch_to_buffer (create_buffer (infile));
  567.     }
  568.       else
  569.     clean_up_and_exit (1);
  570.     }
  571.   else
  572.     {
  573.       switch_to_buffer (create_buffer (get_input_from_stdin ()));
  574.  
  575. // Is input coming from a terminal?  If so, we are probably
  576. // interactive.
  577.  
  578.       interactive = (isatty (fileno (stdin)) && isatty (fileno (stdout)));
  579.     }
  580.  
  581. // Force input to be echoed if not really interactive, but the user
  582. // has forced interactive behavior.
  583.  
  584.   if (!interactive && forced_interactive)
  585.     {
  586.       rl_blink_matching_paren = 0;
  587.       echo_input = 1;
  588.     }
  589.  
  590.   if (! (interactive || forced_interactive))
  591.     using_readline = 0;
  592.  
  593. // Allow the user to interrupt us without exiting.
  594.  
  595.   volatile sig_handler *saved_sigint_handler = signal (SIGINT, SIG_IGN);
  596.  
  597.   if (setjmp (toplevel) != 0)
  598.     {
  599.       raw_mode (0);
  600.  
  601.       cout << "\n";
  602.     }
  603.  
  604.   can_interrupt = 1;
  605.  
  606.   signal (SIGINT, saved_sigint_handler);
  607.  
  608. // The big loop.
  609.  
  610.   int retval;
  611.   do
  612.     {
  613.       curr_sym_tab = top_level_sym_tab;
  614.  
  615.       reset_parser ();
  616.  
  617.       retval = yyparse ();
  618.  
  619.       if (retval == 0 && global_command)
  620.     {
  621.       global_command->eval (1);
  622.       delete global_command;
  623.       current_command_number++;
  624.     }
  625.     }
  626.   while (retval == 0);
  627.  
  628.   if (retval == 1 && ! error_state)
  629.     retval = 0;
  630.  
  631.   clean_up_and_exit (retval);
  632. }
  633.  
  634. DEFUN_TEXT ("casesen", Fcasesen, Scasesen, 2, 1,
  635.   "casesen [on|off]")
  636. {
  637.   Octave_object retval;
  638.  
  639.   DEFINE_ARGV("casesen");
  640.  
  641.   if (argc == 1 || (argc > 1 && strcmp (argv[1], "off") == 0))
  642.     warning ("casesen: sorry, Octave is always case sensitive");
  643.   else if (argc > 1 && strcmp (argv[1], "on") == 0)
  644.     ; // ok.
  645.   else
  646.     print_usage ("casesen");
  647.  
  648.   DELETE_ARGV;
  649.  
  650.   return retval;
  651. }
  652.  
  653. DEFUN ("computer", Fcomputer, Scomputer, 1, 0,
  654.   "computer ():\n\
  655. \n\
  656. Have Octave ask the system, \"What kind of computer are you?\"")
  657. {
  658.   Octave_object retval;
  659.  
  660.   int nargin = args.length ();
  661.  
  662.   if (nargin != 0)
  663.     warning ("computer: ignoring extra arguments");
  664.  
  665.   ostrstream output_buf;
  666.  
  667.   if (strcmp (TARGET_HOST_TYPE, "unknown") == 0)
  668.     output_buf << "Hi Dave, I'm a HAL-9000";
  669.   else
  670.     output_buf << TARGET_HOST_TYPE;
  671.  
  672.   if (nargout == 0)
  673.     {
  674.       output_buf << "\n" << ends;
  675.       maybe_page_output (output_buf);
  676.     }
  677.   else
  678.     {
  679.       output_buf << ends;
  680.       char *msg = output_buf.str ();
  681.       retval = msg;
  682.       delete [] msg;
  683.     }
  684.  
  685.   return retval;
  686. }
  687.  
  688. DEFUN ("flops", Fflops, Sflops, 0, 1,
  689.   "flops (): count floating point operations")
  690. {
  691.   int nargin = args.length ();
  692.  
  693.   if (nargin > 0)
  694.     print_usage ("flops");
  695.  
  696.   warning ("flops is a flop, always returning zero");
  697.  
  698.   return 0.0;
  699. }
  700.  
  701. DEFUN ("quit", Fquit, Squit, 0, 0,
  702.   "quit (): exit Octave gracefully")
  703. {
  704.   Octave_object retval;
  705.   quitting_gracefully = 1;
  706.   clean_up_and_exit (0);
  707.   return retval;
  708. }
  709.  
  710. DEFALIAS (exit, quit);
  711.  
  712. DEFUN ("warranty", Fwarranty, Swarranty, 0, 0,
  713.   "warranty (): describe copying conditions")
  714. {
  715.   Octave_object retval;
  716.  
  717.   ostrstream output_buf;
  718.   output_buf << "\n" OCTAVE_NAME_VERSION_AND_COPYRIGHT "\n\n\
  719. This program is free software; you can redistribute it and/or modify\n\
  720. it under the terms of the GNU General Public License as published by\n\
  721. the Free Software Foundation; either version 2 of the License, or\n\
  722. (at your option) any later version.\n\
  723. \n\
  724. This program is distributed in the hope that it will be useful,\n\
  725. but WITHOUT ANY WARRANTY; without even the implied warranty of\n\
  726. MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n\
  727. GNU General Public License for more details.\n\
  728. \n\
  729. You should have received a copy of the GNU General Public License\n\
  730. along with this program. If not, write to the Free Software\n\
  731. Foundation, 675 Mass Ave, Cambridge, MA 02139, USA.\n\
  732. \n";
  733.  
  734.   output_buf << ends;
  735.   maybe_page_output (output_buf);
  736.  
  737.   return retval;
  738. }
  739.  
  740. // XXX FIXME XXX -- this may not be the best place for these...
  741.  
  742. Octave_object
  743. feval (const Octave_object& args, int nargout)
  744. {
  745.   Octave_object retval;
  746.  
  747.   tree_fvc *fcn = is_valid_function (args(0), "feval", 1);
  748.   if (fcn)
  749.     {
  750.       int tmp_nargin = args.length () - 1;
  751.       Octave_object tmp_args;
  752.       tmp_args.resize (tmp_nargin);
  753.       for (int i = 0; i < tmp_nargin; i++)
  754.     tmp_args(i) = args(i+1);
  755.       retval = fcn->eval (0, nargout, tmp_args);
  756.     }
  757.  
  758.   return retval;
  759. }
  760.  
  761. DEFUN ("feval", Ffeval, Sfeval, -1, 1,
  762.   "feval (NAME, ARGS, ...)\n\
  763. \n\
  764. evaluate NAME as a function, passing ARGS as its arguments")
  765. {
  766.   Octave_object retval;
  767.  
  768.   int nargin = args.length ();
  769.  
  770.   if (nargin > 0)
  771.     retval = feval (args, nargout);
  772.   else
  773.     print_usage ("feval");
  774.  
  775.   return retval;
  776. }
  777.  
  778. static Octave_object
  779. eval_string (const char *string, int print, int ans_assign,
  780.          int& parse_status, int nargout)
  781. {
  782.   begin_unwind_frame ("eval_string");
  783.  
  784.   unwind_protect_int (get_input_from_eval_string);
  785.   unwind_protect_ptr (global_command);
  786.   unwind_protect_ptr (current_eval_string);
  787.  
  788.   get_input_from_eval_string = 1;
  789.   current_eval_string = string;
  790.  
  791.   YY_BUFFER_STATE old_buf = current_buffer ();
  792.   YY_BUFFER_STATE new_buf = create_buffer (0);
  793.  
  794.   add_unwind_protect (restore_input_buffer, (void *) old_buf);
  795.   add_unwind_protect (delete_input_buffer, (void *) new_buf);
  796.  
  797.   switch_to_buffer (new_buf);
  798.  
  799.   unwind_protect_ptr (curr_sym_tab);
  800.  
  801.   reset_parser ();
  802.  
  803.   parse_status = yyparse ();
  804.  
  805. // Important to reset the idea of where input is coming from before
  806. // trying to eval the command we just parsed -- it might contain the
  807. // name of an function file that still needs to be parsed!
  808.  
  809.   tree_statement_list *command = global_command;
  810.  
  811.   run_unwind_frame ("eval_string");
  812.  
  813.   Octave_object retval;
  814.  
  815.   if (parse_status == 0 && command)
  816.     {
  817.       retval = command->eval (print, nargout);
  818.       delete command;
  819.     }
  820.  
  821.   return retval;
  822. }
  823.  
  824. tree_constant
  825. eval_string (const char *string, int print, int ans_assign,
  826.          int& parse_status)
  827. {
  828.   tree_constant retval;
  829.  
  830.   Octave_object tmp = eval_string (string, print, ans_assign,
  831.                    parse_status, 1);
  832.  
  833.   retval = tmp(0);
  834.  
  835.   return retval;
  836. }
  837.  
  838. static Octave_object
  839. eval_string (const tree_constant& arg, int& parse_status, int nargout)
  840. {
  841.   char *string = arg.string_value ();
  842.  
  843.   if (error_state)
  844.     {
  845.       error ("eval: expecting string argument");
  846.       return -1.0;
  847.     }
  848.  
  849. // Yes Virginia, we always print here...
  850.  
  851.   return eval_string (string, 1, 1, parse_status, nargout);
  852. }
  853.  
  854. DEFUN ("eval", Feval, Seval, 2, 1,
  855.   "eval (TRY, CATCH)\n\
  856. \n\
  857. Evaluate the string TRY as octave code.  If that fails, evaluate the\n\
  858. string CATCH.")
  859. {
  860.   Octave_object retval;
  861.  
  862.   int nargin = args.length ();
  863.  
  864.   if (nargin > 0)
  865.     {
  866.       begin_unwind_frame ("Feval");
  867.  
  868.       if (nargin > 1)
  869.     {
  870.       unwind_protect_int (suppress_octave_error_messages);
  871.       suppress_octave_error_messages = 1;
  872.     }
  873.  
  874.       int parse_status = 0;
  875.  
  876.       retval = eval_string (args(0), parse_status, nargout);
  877.  
  878.       if (nargin > 1 && (parse_status != 0 || error_state))
  879.     {
  880.       error_state = 0;
  881.       eval_string (args(1), parse_status, nargout);
  882.       retval = Octave_object ();
  883.     }
  884.  
  885.       run_unwind_frame ("Feval");
  886.     }
  887.   else
  888.     print_usage ("eval");
  889.  
  890.   return retval;
  891. }
  892.  
  893. // Execute a shell command.
  894.  
  895. DEFUN ("system", Fsystem, Ssystem, 2, 1,
  896.   "system (string [, return_output]): execute shell commands")
  897. {
  898.   Octave_object retval;
  899.  
  900.   int nargin = args.length ();
  901.  
  902.   if (nargin < 1 || nargin > 2)
  903.     {
  904.       print_usage ("system");
  905.       return retval;
  906.     }
  907.  
  908.   tree_constant tc_command = args(0);
  909.  
  910.   char *tmp_str = tc_command.string_value ();
  911.  
  912.   if (error_state)
  913.     {
  914.       error ("system: expecting string as first argument");
  915.     }
  916.   else
  917.     {
  918.       iprocstream cmd (tmp_str);
  919.  
  920.       ostrstream output_buf;
  921.  
  922.       char ch;
  923.       while (cmd.get (ch))
  924.     output_buf.put (ch);
  925.  
  926.       output_buf << ends;
  927.  
  928.       int status = cmd.close ();
  929.  
  930. // The value in status is as returned by waitpid.  If the process
  931. // exited normally, extract the actual exit status of the command.
  932. // Otherwise, return 127 as a failure code.
  933.  
  934.       if ((status & 0xff) == 0)
  935.     status = (status & 0xff00) >> 8;
  936.       else
  937.     status = 127;
  938.  
  939.       if (nargout > 0 || nargin > 1)
  940.     {
  941.       char *msg = output_buf.str ();
  942.  
  943.       retval(1) = (double) status;
  944.       retval(0) = msg;
  945.  
  946.       delete [] msg;
  947.     }
  948.       else
  949.     maybe_page_output (output_buf);
  950.     }
  951.  
  952.   return retval;
  953. }
  954.  
  955. DEFALIAS (shell_cmd, system);
  956.  
  957. /*
  958. ;;; Local Variables: ***
  959. ;;; mode: C++ ***
  960. ;;; page-delimiter: "^/\\*" ***
  961. ;;; End: ***
  962. */
  963.