GNU Octave  3.8.0
A high-level interpreted language, primarily intended for numerical computations, mostly compatible with Matlab
 All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Properties Friends Macros Pages
octave.cc
Go to the documentation of this file.
1 /*
2 
3 Copyright (C) 1993-2013 John W. Eaton
4 
5 This file is part of Octave.
6 
7 Octave is free software; you can redistribute it and/or modify it
8 under the terms of the GNU General Public License as published by the
9 Free Software Foundation; either version 3 of the License, or (at your
10 option) any later version.
11 
12 Octave is distributed in the hope that it will be useful, but WITHOUT
13 ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
14 FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
15 for more details.
16 
17 You should have received a copy of the GNU General Public License
18 along with Octave; see the file COPYING. If not, see
19 <http://www.gnu.org/licenses/>.
20 
21 */
22 
23 // Born February 20, 1992.
24 
25 #ifdef HAVE_CONFIG_H
26 #include <config.h>
27 #endif
28 
29 #include <cassert>
30 #include <clocale>
31 #include <cstdlib>
32 #include <cstring>
33 #include <ctime>
34 
35 #include <iostream>
36 
37 #include <fcntl.h>
38 #include <getopt.h>
39 #include <sys/types.h>
40 #include <unistd.h>
41 
42 #include "cmd-edit.h"
43 #include "f77-fcn.h"
44 #include "file-ops.h"
45 #include "file-stat.h"
46 #include "lo-error.h"
47 #include "oct-env.h"
48 #include "str-vec.h"
49 
50 #include "builtins.h"
51 #include "defaults.h"
52 #include "Cell.h"
53 #include "defun.h"
54 #include "display.h"
55 #include "error.h"
56 #include "file-io.h"
57 #include "help.h"
58 #include "input.h"
59 #include "lex.h"
60 #include "load-path.h"
61 #include "load-save.h"
62 #include "octave.h"
63 #include "oct-conf.h"
64 #include "oct-hist.h"
65 #include "oct-map.h"
66 #include "oct-mutex.h"
67 #include "oct-obj.h"
68 #include "ops.h"
69 #include "options-usage.h"
70 #include "ov.h"
71 #include "ov-range.h"
72 #include "toplev.h"
73 #include "parse.h"
74 #include "procstream.h"
75 #include "sighandlers.h"
76 #include "sysdep.h"
77 #include "unwind-prot.h"
78 #include "utils.h"
79 #include "variables.h"
80 #include <version.h>
81 
82 // Kluge.
83 extern "C" F77_RET_T
85  const octave_idx_type&
87 
88 extern void install_builtins (void);
89 
93 
94 // The command-line options.
96 
97 // The name used to invoke Octave.
98 static std::string
100 
101 // The last component of octave_program_invocation_name.
102 static std::string octave_program_name;
103 
104 // TRUE means we are using readline.
105 // (--no-line-editing)
106 static bool line_editing = true;
107 
108 // TRUE means we read ~/.octaverc and ./.octaverc.
109 // (--norc; --no-init-file; -f)
110 static bool read_init_files = true;
111 
112 // TRUE means we read the site-wide octaverc files.
113 // (--norc; --no-site-file; -f)
114 static bool read_site_files = true;
115 
116 // TRUE means we set the initial path to configured defaults.
117 // (--no-init-path)
118 static bool set_initial_path = true;
119 
120 // TRUE means we don't print the usual startup message.
121 // (--quiet; --silent; -q)
122 static bool inhibit_startup_message = false;
123 
124 // If TRUE, print verbose info in some cases.
125 // (--verbose; -V)
126 static bool verbose_flag = false;
127 
128 // If TRUE, force the GUI to start.
129 // (--force-gui)
130 static bool force_gui_option = false;
131 
132 // If TRUE don't start the GUI.
133 // (--no-gui)
134 static bool no_gui_option = false;
135 
136 // If TRUE, force readline command line editing.
137 // (--line-editing)
138 static bool forced_line_editing = false;
139 
140 // If TRUE, initialize history list from saved history file.
141 // (--no-history; -H)
142 static bool read_history_file = true;
143 
144 // The value of "path" specified on the command line.
145 // (--path; -p)
146 static std::list<std::string> command_line_path;
147 
148 // The value for "EXEC_PATH" specified on the command line.
149 // (--exec-path)
150 static std::string exec_path;
151 
152 // The value for "IMAGE_PATH" specified on the command line.
153 // (--image-path)
154 static std::string image_path;
155 
156 // If TRUE, ignore the window system even if it is available.
157 // (--no-window-system, -W)
158 static bool no_window_system = false;
159 
160 // The code to evaluate at startup (--eval CODE)
161 static std::string code_to_eval;
162 
163 // If TRUE, don't exit after evaluating code given by --eval option.
164 static bool persist = false;
165 
166 // If TRUE, the GUI should be started.
167 static bool start_gui = false;
168 
169 // If TRUE use traditional settings (--traditional)
170 static bool traditional = false;
171 
172 // Store the command-line options for later use.
173 
174 static void
175 intern_argv (int argc, char **argv)
176 {
177  assert (symbol_table::at_top_level ());
178 
179  symbol_table::assign (".nargin.", argc - 1);
180 
181  symbol_table::mark_hidden (".nargin.");
182 
183  if (argc > 0)
184  {
185  octave_argv.resize (argc - 1);
186 
187  // Skip program name in argv.
188  int i = argc;
189  while (--i > 0)
190  octave_argv[i-1] = *(argv+i);
191  }
192 }
193 
194 DEFUN (__version_info__, args, ,
195  "-*- texinfo -*-\n\
196 @deftypefn {Built-in Function} {retval =} __version_info__ (@var{name}, @var{version}, @var{release}, @var{date})\n\
197 Undocumented internal function.\n\
198 @end deftypefn")
199 {
200  octave_value retval;
201 
202  static octave_map vinfo;
203 
204  int nargin = args.length ();
205 
206  if (nargin == 4)
207  {
208  if (vinfo.nfields () == 0)
209  {
210  vinfo.assign ("Name", args (0));
211  vinfo.assign ("Version", args (1));
212  vinfo.assign ("Release", args (2));
213  vinfo.assign ("Date", args (3));
214  }
215  else
216  {
217  octave_idx_type n = vinfo.numel () + 1;
218 
219  vinfo.resize (dim_vector (n, 1));
220 
221  octave_value idx (n);
222 
223  vinfo.assign (idx, "Name", Cell (octave_value (args (0))));
224  vinfo.assign (idx, "Version", Cell (octave_value (args (1))));
225  vinfo.assign (idx, "Release", Cell (octave_value (args (2))));
226  vinfo.assign (idx, "Date", Cell (octave_value (args (3))));
227  }
228  }
229  else if (nargin == 0)
230  retval = vinfo;
231  else
232  print_usage ();
233 
234  return retval;
235 }
236 
237 static void
239 {
240  octave_value_list args;
241 
242  args(3) = OCTAVE_RELEASE_DATE;
243  args(2) = OCTAVE_RELEASE;
244  args(1) = OCTAVE_VERSION;
245  args(0) = "GNU Octave";
246 
247  F__version_info__ (args, 0);
248 }
249 
250 static void
251 gripe_safe_source_exception (const std::string& file, const std::string& msg)
252 {
253  std::cerr << "error: " << msg << "\n"
254  << "error: execution of " << file << " failed\n"
255  << "error: trying to make my way to a command prompt"
256  << std::endl;
257 }
258 
259 // Execute commands from a file and catch potential exceptions in a
260 // consistent way. This function should be called anywhere we might
261 // parse and execute commands from a file before before we have entered
262 // the main loop in toplev.cc.
263 
264 static void
265 safe_source_file (const std::string& file_name,
266  const std::string& context = std::string (),
267  bool verbose = false, bool require_file = true,
268  const std::string& warn_for = std::string ())
269 {
270  try
271  {
272  source_file (file_name, context, verbose, require_file, warn_for);
273  }
274  catch (octave_interrupt_exception)
275  {
277  octave_stdout << "\n";
280  }
281  catch (octave_execution_exception)
282  {
284  gripe_safe_source_exception (file_name, "unhandled execution exception");
285  }
286 }
287 
288 // Initialize by reading startup files.
289 
290 static void
292 {
293  unwind_protect frame;
294 
295  std::string context;
296 
297  bool verbose = (verbose_flag && ! inhibit_startup_message);
298 
299  bool require_file = false;
300 
301  if (read_site_files)
302  {
303  // Execute commands from the site-wide configuration file.
304  // First from the file $(prefix)/lib/octave/site/m/octaverc
305  // (if it exists), then from the file
306  // $(prefix)/share/octave/$(version)/m/octaverc (if it exists).
307 
308  safe_source_file (Vlocal_site_defaults_file, context, verbose,
309  require_file);
310 
311  safe_source_file (Vsite_defaults_file, context, verbose, require_file);
312  }
313 
314  if (read_init_files)
315  {
316  // Try to execute commands from $HOME/$OCTAVE_INITFILE and
317  // $OCTAVE_INITFILE. If $OCTAVE_INITFILE is not set, .octaverc
318  // is assumed.
319 
320  bool home_rc_already_executed = false;
321 
322  std::string initfile = octave_env::getenv ("OCTAVE_INITFILE");
323 
324  if (initfile.empty ())
325  initfile = ".octaverc";
326 
327  std::string home_dir = octave_env::get_home_directory ();
328 
329  std::string home_rc = octave_env::make_absolute (initfile, home_dir);
330 
331  std::string local_rc;
332 
333  if (! home_rc.empty ())
334  {
335  safe_source_file (home_rc, context, verbose, require_file);
336 
337  // Names alone are not enough.
338 
339  file_stat fs_home_rc (home_rc);
340 
341  if (fs_home_rc)
342  {
343  // We want to check for curr_dir after executing home_rc
344  // because doing that may change the working directory.
345 
346  local_rc = octave_env::make_absolute (initfile);
347 
348  home_rc_already_executed = same_file (home_rc, local_rc);
349  }
350  }
351 
352  if (! home_rc_already_executed)
353  {
354  if (local_rc.empty ())
355  local_rc = octave_env::make_absolute (initfile);
356 
357  safe_source_file (local_rc, context, verbose, require_file);
358  }
359  }
360 }
361 
362 static int
363 execute_eval_option_code (const std::string& code)
364 {
365  unwind_protect frame;
366 
368 
369  can_interrupt = true;
370 
374 
376 
377  octave_initialized = true;
378 
379  frame.protect_var (interactive);
380 
381  interactive = false;
382 
383  int parse_status = 0;
384 
385  try
386  {
387  eval_string (code, false, parse_status, 0);
388  }
389  catch (octave_interrupt_exception)
390  {
392  octave_stdout << "\n";
395  }
396  catch (octave_execution_exception)
397  {
399  std::cerr << "error: unhandled execution exception -- eval failed"
400  << std::endl;
401  }
402 
403  return parse_status;
404 }
405 
406 static void
407 execute_command_line_file (const std::string& fname)
408 {
409  unwind_protect frame;
410 
412 
413  can_interrupt = true;
414 
418 
420 
421  octave_initialized = true;
422 
423  frame.protect_var (interactive);
424 
427 
428  interactive = false;
429 
431 
432  size_t pos = fname.find_last_of (file_ops::dir_sep_chars ());
433 
435  = (pos != std::string::npos) ? fname.substr (pos+1) : fname;
436 
437  std::string context;
438  bool verbose = false;
439  bool require_file = true;
440 
441  safe_source_file (fname, context, verbose, require_file, "octave");
442 }
443 
444 static void
445 lo_error_handler (const char *fmt, ...)
446 {
447  va_list args;
448  va_start (args, fmt);
449  verror_with_cfn (fmt, args);
450  va_end (args);
451 
453 }
454 
455 static void
456 lo_error_with_id_handler (const char *id, const char *fmt, ...)
457 {
458  va_list args;
459  va_start (args, fmt);
460  verror_with_id_cfn (id, fmt, args);
461  va_end (args);
462 
464 }
465 
466 static void
468 {
473 }
474 
475 // What happens on --traditional.
476 
477 static void
479 {
480  persist = true;
481 
482  FPS1 (octave_value (">> "));
483  FPS2 (octave_value (""));
484  FPS4 (octave_value (""));
486  Fbeep_on_error (octave_value (true));
489  Fsave_default_options (octave_value ("-mat-binary"));
492  Fhistory_timestamp_format_string (octave_value ("%%-- %D %I:%M %p --%%"));
495 
496  disable_warning ("Octave:abbreviated-property-match");
497  disable_warning ("Octave:fopen-file-in-path");
498  disable_warning ("Octave:function-name-clash");
499  disable_warning ("Octave:load-file-in-path");
500  disable_warning ("Octave:possible-matlab-short-circuit-operator");
501 
502  // Initialized to "error" by default.
503  set_warning_state ("Octave:noninteger-range-as-index", "on");
504 }
505 
506 // EMBEDDED is declared int instead of bool because this function is
507 // declared extern "C".
508 
509 int
510 octave_main (int argc, char **argv, int embedded)
511 {
512  octave_process_command_line (argc, argv);
513 
514  sysdep_init ();
515 
516  install_defaults ();
517 
518  octave_initialize_interpreter (argc, argv, embedded);
519 
520  return octave_execute_interpreter ();
521 }
522 
523 void
524 octave_process_command_line (int argc, char **argv)
525 {
526  octave_cmdline_argc = argc;
527  octave_cmdline_argv = argv;
528 
529  while (true)
530  {
531  int long_idx;
532 
533  int optc = getopt_long (argc, argv, short_opts, long_opts, &long_idx);
534 
535  if (optc < 0)
536  break;
537 
538  switch (optc)
539  {
540  case '?':
541  // Unrecognized option. getopt_long already printed a
542  // message about that, so we will just print the usage string
543  // and exit.
545  break;
546 
547  case 'H':
548  Fhistory_save (octave_value (false));
549  read_history_file = false;
550  break;
551 
552  case 'W':
553  no_window_system = true;
554  break;
555 
556  case 'V':
557  verbose_flag = true;
558  break;
559 
560  case 'd':
561  // This is the same as yydebug in parse.y.
562  octave_debug++;
563  break;
564 
565  case 'f':
566  read_init_files = false;
567  read_site_files = false;
568  break;
569 
570  case 'h':
572  break;
573 
574  case 'i':
575  forced_interactive = true;
576  break;
577 
578  case 'p':
579  if (optarg)
580  command_line_path.push_back (optarg);
581  break;
582 
583  case 'q':
585  break;
586 
587  case 'x':
588  {
591  }
592  break;
593 
594  case 'v':
596  break;
597 
599  if (optarg)
601  break;
602 
604  if (optarg)
605  Fdoc_cache_file (octave_value (optarg));
606  break;
607 
608  case EVAL_OPTION:
609  if (optarg)
610  {
611  if (code_to_eval.empty ())
612  code_to_eval = optarg;
613  else
614  code_to_eval += std::string (" ") + optarg;
615  }
616  break;
617 
618  case EXEC_PATH_OPTION:
619  if (optarg)
620  exec_path = optarg;
621  break;
622 
623  case FORCE_GUI_OPTION:
624  force_gui_option = true;
625  break;
626 
627  case IMAGE_PATH_OPTION:
628  if (optarg)
629  image_path = optarg;
630  break;
631 
632  case INFO_FILE_OPTION:
633  if (optarg)
634  Finfo_file (octave_value (optarg));
635  break;
636 
637  case INFO_PROG_OPTION:
638  if (optarg)
639  Finfo_program (octave_value (optarg));
640  break;
641 
642  case DEBUG_JIT_OPTION:
643  Fdebug_jit (octave_value (true));
644  break;
645 
646  case JIT_COMPILER_OPTION:
647  Fjit_enable (octave_value (true));
648  break;
649 
650  case LINE_EDITING_OPTION:
651  forced_line_editing = true;
652  break;
653 
654  case NO_GUI_OPTION:
655  no_gui_option = true;
656  break;
657 
658  case NO_INIT_FILE_OPTION:
659  read_init_files = false;
660  break;
661 
662  case NO_INIT_PATH_OPTION:
663  set_initial_path = false;
664  break;
665 
667  line_editing = false;
668  break;
669 
670  case NO_SITE_FILE_OPTION:
671  read_site_files = 0;
672  break;
673 
674  case PERSIST_OPTION:
675  persist = true;
676  break;
677 
679  if (optarg)
680  Ftexi_macros_file (octave_value (optarg));
681  break;
682 
683  case TRADITIONAL_OPTION:
684  traditional = true;
685  break;
686 
687  default:
688  // getopt_long should print a message about unrecognized
689  // options and return '?', which is handled above. So if we
690  // end up here, it is because there was an option but we
691  // forgot to handle it. That should be fatal.
692  panic_impossible ();
693  break;
694  }
695  }
696 
698  {
699  error ("error: only one of --force-gui and --no-gui may be used");
700 
702  }
703 }
704 
705 // EMBEDDED is declared int instead of bool because this function is
706 // declared extern "C".
707 
708 void
709 octave_initialize_interpreter (int argc, char **argv, int embedded)
710 {
711  // Matlab uses "C" locale for LC_NUMERIC class regardless of local setting
712  setlocale (LC_NUMERIC, "C");
713  setlocale (LC_TIME, "C");
714 
715  octave_embedded = embedded;
716 
718 
721 
723 
725 
726  // Initialize default warning state before --traditional option may
727  // reset them.
728 
730 
731  if (traditional)
733 
734  init_signals ();
735 
736  octave_ieee_init ();
737 
738  // The idea here is to force xerbla to be referenced so that we will
739  // link to our own version instead of the one provided by the BLAS
740  // library. But octave_NaN should never be -1, so we should never
741  // actually call xerbla.
742 
743  if (octave_NaN == -1)
744  F77_FUNC (xerbla, XERBLA) ("octave", 13 F77_CHAR_ARG_LEN (6));
745 
747 
748  if (! embedded)
750  else
751  quit_allowed = false;
752 
754 
755  install_types ();
756 
757  install_ops ();
758 
759  install_builtins ();
760 
761  for (std::list<std::string>::const_iterator it = command_line_path.begin ();
762  it != command_line_path.end (); it++)
764 
765  if (! exec_path.empty ())
767 
768  if (! image_path.empty ())
770 
771  if (no_window_system)
773 
774  // Is input coming from a terminal? If so, we are probably
775  // interactive.
776 
777  // If stdin is not a tty, then we are reading commands from a pipe or
778  // a redirected file.
779  bool stdin_is_tty = gnulib::isatty (fileno (stdin));
780 
781  interactive = (! embedded && stdin_is_tty
782  && gnulib::isatty (fileno (stdout)));
783 
784  if (! interactive && ! forced_line_editing)
785  line_editing = false;
786 
787  // Force default line editor if we don't want readline editing.
788  if (! line_editing)
790 
791  // These can come after command line args since none of them set any
792  // defaults that might be changed by command line options.
793 
794  if (line_editing)
796 
798 
800 
801  // Make all command-line arguments available to startup files,
802  // including PKG_ADD files.
803 
804  intern_argv (argc, argv);
805 
807 
809 }
810 
811 int
813 {
815  std::cout << octave_startup_message () << "\n" << std::endl;
816 
818 
820 
822  std::cout << std::endl;
823 
824  // If there is an extra argument, see if it names a file to read.
825  // Additional arguments are taken as command line options for the
826  // script.
827 
828  int last_arg_idx = optind;
829 
830  int remaining_args = octave_cmdline_argc - last_arg_idx;
831 
832  if (! code_to_eval.empty ())
833  {
834  int parse_status = execute_eval_option_code (code_to_eval);
835 
836  if (! (persist || remaining_args > 0))
837  {
838  quitting_gracefully = true;
839 
840  clean_up_and_exit (parse_status || error_state ? 1 : 0);
841  }
842  }
843 
844  if (remaining_args > 0)
845  {
846  // If we are running an executable script (#! /bin/octave) then
847  // we should only see the args passed to the script.
848 
849  intern_argv (remaining_args, octave_cmdline_argv+last_arg_idx);
850 
851  execute_command_line_file (octave_cmdline_argv[last_arg_idx]);
852 
853  if (! persist)
854  {
855  quitting_gracefully = true;
856 
857  clean_up_and_exit (error_state ? 1 : 0);
858  }
859  }
860 
861  // Avoid counting commands executed from startup files.
862 
864 
865  // Now argv should have the full set of args.
866  intern_argv (octave_cmdline_argc, octave_cmdline_argv);
867 
868  // Force input to be echoed if not really interactive, but the user
869  // has forced interactive behavior.
870 
872  {
874 
875  // FIXME: is this the right thing to do?
876 
878  }
879 
880  if (octave_embedded)
881  {
882  // FIXME: do we need to do any cleanup here before
883  // returning? If we don't, what will happen to Octave functions
884  // that have been registered to execute with atexit, for example?
885 
886  return 1;
887  }
888 
889  int retval = main_loop ();
890 
891  quitting_gracefully = true;
892 
893  clean_up_and_exit (retval, true);
894 
895  return retval;
896 }
897 
898 static bool
900 {
901  if (no_window_system)
902  return false;
903 
904  std::string err_msg;
905  if (! display_info::display_available (err_msg))
906  {
907  if (! (inhibit_startup_message || err_msg.empty ()))
908  warning (err_msg.c_str ());
909 
910  return false;
911  }
912 
913  if (force_gui_option)
914  return true;
915 
916  if (no_gui_option)
917  return false;
918 
919  if (persist)
920  return true;
921 
922  // If stdin is not a tty, then assume we are reading commands from a
923  // pipe or a redirected file and the GUI should not start. If this is
924  // not the case (for example, starting from a desktop "launcher" with
925  // no terminal) and you want to start the GUI, you may use the
926  // --force-gui option to start the GUI.
927 
928  if (! gnulib::isatty (fileno (stdin)))
929  return false;
930 
931  // If we have code to eval or execute from a file, and we are going to
932  // exit immediately after executing it, don't start the gui.
933 
934  int last_arg_idx = optind;
935  int remaining_args = octave_cmdline_argc - last_arg_idx;
936 
937  if (! code_to_eval.empty () || remaining_args > 0)
938  return false;
939 
940  return true;
941 }
942 
943 // Return int instead of bool because this function is declared
944 // extern "C".
945 
946 int
948 {
950  return start_gui;
951 }
952 
953 DEFUN (isguirunning, args, ,
954  "-*- texinfo -*-\n\
955 @deftypefn {Built-in Function} {} isguirunning ()\n\
956 Return true if Octave is running in GUI mode and false otherwise.\n\
957 @end deftypefn")
958 {
959  octave_value retval;
960 
961  if (args.length () == 0)
962  retval = start_gui;
963  else
964  print_usage ();
965 
966  return retval;
967 }
968 
969 /*
970 %!assert (islogical (isguirunning ()))
971 %!error isguirunning (1)
972 */
973 
974 DEFUN (argv, args, ,
975  "-*- texinfo -*-\n\
976 @deftypefn {Built-in Function} {} argv ()\n\
977 Return the command line arguments passed to Octave. For example,\n\
978 if you invoked Octave using the command\n\
979 \n\
980 @example\n\
981 octave --no-line-editing --silent\n\
982 @end example\n\
983 \n\
984 @noindent\n\
985 @code{argv} would return a cell array of strings with the elements\n\
986 @option{--no-line-editing} and @option{--silent}.\n\
987 \n\
988 If you write an executable Octave script, @code{argv} will return the\n\
989 list of arguments passed to the script. @xref{Executable Octave Programs},\n\
990 for an example of how to create an executable Octave script.\n\
991 @end deftypefn")
992 {
993  octave_value retval;
994 
995  if (args.length () == 0)
996  retval = Cell (octave_argv);
997  else
998  print_usage ();
999 
1000  return retval;
1001 }
1002 
1003 /*
1004 %!assert (iscellstr (argv ()))
1005 %!error argv (1)
1006 */
1007 
1008 DEFUN (program_invocation_name, args, ,
1009  "-*- texinfo -*-\n\
1010 @deftypefn {Built-in Function} {} program_invocation_name ()\n\
1011 Return the name that was typed at the shell prompt to run Octave.\n\
1012 \n\
1013 If executing a script from the command line (e.g., @code{octave foo.m})\n\
1014 or using an executable Octave script, the program name is set to the\n\
1015 name of the script. @xref{Executable Octave Programs}, for an example of\n\
1016 how to create an executable Octave script.\n\
1017 @seealso{program_name}\n\
1018 @end deftypefn")
1019 {
1020  octave_value retval;
1021 
1022  if (args.length () == 0)
1024  else
1025  print_usage ();
1026 
1027  return retval;
1028 }
1029 
1030 /*
1031 %!assert (ischar (program_invocation_name ()))
1032 %!error program_invocation_name (1)
1033 */
1034 
1035 DEFUN (program_name, args, ,
1036  "-*- texinfo -*-\n\
1037 @deftypefn {Built-in Function} {} program_name ()\n\
1038 Return the last component of the value returned by\n\
1039 @code{program_invocation_name}.\n\
1040 @seealso{program_invocation_name}\n\
1041 @end deftypefn")
1042 {
1043  octave_value retval;
1044 
1045  if (args.length () == 0)
1046  retval = octave_program_name;
1047  else
1048  print_usage ();
1049 
1050  return retval;
1051 }
1052 
1053 /*
1054 %!assert (ischar (program_name ()))
1055 %!error program_name (1)
1056 */