changeset 2926:66ef74ee5d9f

[project @ 1997-05-05 03:20:52 by jwe]
author jwe
date Mon, 05 May 1997 03:40:21 +0000
parents f0665dac8e33
children 8722c6284b72
files liboctave/ChangeLog liboctave/Makefile.in liboctave/cmd-edit.cc liboctave/cmd-edit.h liboctave/cmd-hist.cc liboctave/cmd-hist.h liboctave/dir-ops.cc liboctave/file-ops.cc liboctave/file-ops.h liboctave/file-stat.cc liboctave/file-stat.h liboctave/glob-match.cc liboctave/glob-match.h liboctave/lo-sysdep.cc liboctave/lo-sysdep.h liboctave/lo-utils.cc liboctave/lo-utils.h liboctave/mach-info.cc liboctave/mach-info.h liboctave/oct-env.cc liboctave/oct-env.h liboctave/statdefs.h liboctave/str-vec.cc src/Makefile.in src/defaults.cc src/dirfns.cc src/dynamic-ld.cc src/dynamic-ld.h src/file-io.cc src/fn-cache.cc src/help.cc src/lex.l src/load-save.cc src/oct-hist.cc src/oct-hist.h src/oct-stream.cc src/oct-stream.h src/octave.cc src/ov-typeinfo.cc src/ov-typeinfo.h src/pager.cc src/pr-output.cc src/pt-plot.cc src/sighandlers.cc src/sighandlers.h src/symtab.cc src/syscalls.cc src/sysdep.cc src/sysdep.h src/toplev.cc src/toplev.h src/utils.cc src/utils.h src/variables.cc
diffstat 54 files changed, 3770 insertions(+), 1608 deletions(-) [+]
line wrap: on
line diff
--- a/liboctave/ChangeLog
+++ b/liboctave/ChangeLog
@@ -1,3 +1,36 @@
+Sun May  4 22:17:08 1997  John W. Eaton  <jwe@bevo.che.wisc.edu>
+
+	* statdefs.h: Only include sys/types.h if HAVE_SYS_STAT_H is defined.
+
+	* mach-info.h, mach-info.cc: Add missing const qualifiers.
+	(instance_ok ()): New function.
+
+	* glob-match.h, glob-match.cc: Rename from oct-glob.h, oct-glob.cc.
+
+	* cmd-hist.h, cmd-hist.cc: Make it work without GNU readline.
+
+	* lo-utils.h, lo-utils.cc (strsave, octave_putenv): Move here from
+	src/utils.h and src/utils.cc.
+	(octave_fgets): New function, extracted from src/input.cc.
+
+	* cmd-edit.h, cmd-edit.cc: New files.  Provide wrapper class for
+	GNU readline, and allow Octave to work without GNU readline.
+
+	* lo-sysdep.h, lo-sysdep.cc: New files for miscellaneous
+	system-dependent functions.
+
+	* oct-env.h, oct-env.cc: New files for process environment stuff.
+
+	* file-stat.h, file-stat.cc: New files.  Extract file_stat class
+	from file-ops.h and file-ops.cc and move here.
+
+	* file-ops.h, file-ops.cc: Wrap functions in struct.  Move
+	tilde_expand functions here from src/dirfns.cc.
+
+Fri May  2 19:50:12 1997  John W. Eaton  <jwe@bevo.che.wisc.edu>
+
+	* pathlen.h: New file, from ../src.
+
 Tue Apr 29 04:39:01 1997  John W. Eaton  <jwe@bevo.che.wisc.edu>
 
 	* Array2-idx.h (Array2<T>::maybe_delete_elements): Prevent
--- a/liboctave/Makefile.in
+++ b/liboctave/Makefile.in
@@ -43,11 +43,12 @@
 INCLUDES := Bounds.h CollocWt.h DAE.h DAEFunc.h DASSL.h FEGrid.h FSQP.h \
 	LinConst.h LP.h LPsolve.h LSODE.h NLConst.h NLEqn.h NLFunc.h \
 	NLP.h NPSOL.h ODE.h ODEFunc.h Objective.h QP.h QPSOL.h Quad.h \
-	Range.h base-de.h base-min.h byte-swap.h cmd-hist.h data-conv.h \
-	dir-ops.h file-ops.h getopt.h idx-vector.h \
-	lo-ieee.h lo-mappers.h lo-utils.h mach-info.h oct-alloc.h \
-	oct-cmplx.h oct-glob.h oct-math.h oct-term.h pathsearch.h \
-	prog-args.h statdefs.h str-vec.h sun-utils.h sysdir.h \
+	Range.h base-de.h base-min.h byte-swap.h cmd-edit.h cmd-hist.h \
+	data-conv.h dir-ops.h file-ops.h file-stat.h getopt.h \
+	glob-match.h idx-vector.h lo-ieee.h lo-mappers.h lo-sysdep.h \
+	lo-utils.h mach-info.h oct-alloc.h oct-cmplx.h oct-env.h \
+	oct-math.h pathsearch.h prog-args.h statdefs.h str-vec.h \
+	sun-utils.h sysdir.h \
 	$(MATRIX_INC) \
 	$(MX_OP_INC)
 
@@ -75,12 +76,13 @@
 
 SOURCES := Bounds.cc CollocWt.cc DAE.cc DASSL.cc FEGrid.cc FSQP.cc \
 	LinConst.cc LPsolve.cc LSODE.cc NLEqn.cc NPSOL.cc QPSOL.cc \
-	Quad.cc Range.cc acosh.c asinh.c atanh.c cmd-hist.cc \
-	data-conv.cc dir-ops.cc erf.c erfc.c f2c-main.c file-ops.cc \
-	filemode.c gamma.c getopt.c getopt1.c idx-vector.cc lgamma.c \
-	lo-ieee.cc lo-mappers.cc lo-utils.cc mach-info.cc mkdir.c \
-	oct-alloc.cc oct-glob.cc oct-term.cc pathsearch.cc \
-	prog-args.cc rename.c rmdir.c str-vec.cc tempname.c tempnam.c \
+	Quad.cc Range.cc acosh.c asinh.c atanh.c cmd-edit.cc \
+	cmd-hist.cc data-conv.cc dir-ops.cc erf.c erfc.c f2c-main.c \
+	file-ops.cc file-stat.cc filemode.c gamma.c getopt.c getopt1.c \
+	glob-match.cc idx-vector.cc lgamma.c lo-ieee.cc lo-mappers.cc \
+	lo-sysdep.cc lo-utils.cc mach-info.cc mkdir.c oct-alloc.cc \
+	oct-env.cc pathsearch.cc prog-args.cc rename.c rmdir.c \
+	str-vec.cc tempname.c tempnam.c \
 	$(TEMPLATE_SRC) \
 	$(TI_SRC) \
 	$(MATRIX_SRC) \
new file mode 100644
--- /dev/null
+++ b/liboctave/cmd-edit.cc
@@ -0,0 +1,850 @@
+/*
+
+Copyright (C) 1996, 1997 John W. Eaton
+
+This file is part of Octave.
+
+Octave is free software; you can redistribute it and/or modify it
+under the terms of the GNU General Public License as published by the
+Free Software Foundation; either version 2, or (at your option) any
+later version.
+
+Octave is distributed in the hope that it will be useful, but WITHOUT
+ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+for more details.
+
+You should have received a copy of the GNU General Public License
+along with Octave; see the file COPYING.  If not, write to the Free
+Software Foundation, 59 Temple Place - Suite 330, Boston, MA  02111-1307, USA.
+
+*/
+
+#ifdef HAVE_CONFIG_H
+#include <config.h>
+#endif
+
+#include <cstring>
+#include <ctime>
+
+#include <string>
+
+#ifdef HAVE_UNISTD_H
+#ifdef HAVE_SYS_TYPES_H
+#include <sys/types.h>
+#endif
+#include <unistd.h>
+#endif
+
+#include "cmd-edit.h"
+#include "cmd-hist.h"
+#include "lo-error.h"
+#include "lo-utils.h"
+#include "oct-env.h"
+
+command_editor *command_editor::instance = 0;
+
+#if defined (USE_READLINE)
+
+#include <cstdio>
+#include <cstdlib>
+
+#include <readline/readline.h>
+
+// It would be nice if readline.h declared these, I think.
+
+extern "C" void rl_deprep_terminal (void);
+
+extern int rl_blink_matching_paren;
+
+extern int screenheight;
+
+extern int screenwidth;
+
+class
+gnu_readline : public command_editor
+{
+public:
+
+  typedef command_editor::fcn fcn;
+
+  gnu_readline (void);
+
+  ~gnu_readline (void) { }
+
+  void do_set_name (const string& n);
+
+  string do_readline (const string& prompt);
+
+  void do_set_input_stream (FILE *f);
+
+  FILE *do_get_input_stream (void);
+
+  void do_set_output_stream (FILE *f);
+
+  FILE *do_get_output_stream (void);
+
+  int do_terminal_rows (void);
+
+  int do_terminal_cols (void);
+
+  void do_clear_screen (void);
+
+  string newline_chars (void);
+
+  void do_restore_terminal_state (void);
+
+  void do_blink_matching_paren (bool flag);
+
+  void do_set_paren_string_delimiters (const string& s);
+
+  void do_set_completion_append_character (char c);
+
+  void do_set_attempted_completion_function (fcn f);
+
+  void do_insert_text (const string& text);
+
+  void do_newline (void);
+
+  void do_clear_undo_list (void);
+
+  void do_set_startup_hook (fcn f);
+
+  void do_restore_startup_hook (void);
+
+  static void operate_and_get_next (int, int);
+
+private:
+
+  fcn previous_startup_hook;
+
+  fcn attempted_completion_function;
+};
+
+gnu_readline::gnu_readline ()
+  : command_editor (), previous_startup_hook (0),
+    attempted_completion_function (0)
+{
+  rl_initialize ();
+
+  do_blink_matching_paren (true);
+
+  // Bind operate-and-get-next.
+
+  rl_add_defun ("operate-and-get-next",
+		gnu_readline::operate_and_get_next, CTRL ('O'));
+
+  // And the history search functions.
+
+  rl_add_defun ("history-search-backward",
+		rl_history_search_backward, META ('p'));
+
+  rl_add_defun ("history-search-forward",
+		rl_history_search_forward, META ('n'));
+}
+
+void
+gnu_readline::do_set_name (const string& n)
+{
+  static char *nm = 0;
+
+  delete [] nm;
+
+  nm = strsave (n.c_str ());
+
+  rl_readline_name = nm;
+
+  // Since we've already called rl_initialize, we need to re-read the
+  // init file to take advantage of the conditional parsing feature
+  // based on rl_readline_name;
+
+  rl_re_read_init_file ();
+}
+
+string
+gnu_readline::do_readline (const string& prompt)
+{
+  string retval;
+
+  char *line = ::readline (prompt.c_str ());
+
+  if (line)
+    {
+      retval = line;
+
+      free (line);
+    }
+
+  return retval;
+}
+
+void
+gnu_readline::do_set_input_stream (FILE *f)
+{
+  rl_instream = f;
+}
+
+FILE *
+gnu_readline::do_get_input_stream (void)
+{
+  return rl_instream;
+}
+
+void
+gnu_readline::do_set_output_stream (FILE *f)
+{
+  rl_outstream = f;
+}
+
+FILE *
+gnu_readline::do_get_output_stream (void)
+{
+  return rl_outstream;
+}
+
+// GNU readline handles SIGWINCH, so these values have a good chance
+// of being correct even if the window changes size (they may be
+// wrong if, for example, the luser changes the window size while the
+// pager is running, and the signal is handled by the pager instead of
+// us.
+
+int
+gnu_readline::do_terminal_rows (void)
+{
+  return screenheight > 0 ? screenheight : 24;
+}
+
+int
+gnu_readline::do_terminal_cols (void)
+{
+  return screenwidth > 0 ? screenwidth : 80;
+}
+
+void
+gnu_readline::do_clear_screen (void)
+{
+  rl_clear_screen ();
+}
+
+string
+gnu_readline::newline_chars (void)
+{
+  return "\r\n";
+}
+
+void
+gnu_readline::do_restore_terminal_state (void)
+{
+  rl_deprep_terminal ();
+}
+
+void
+gnu_readline::do_blink_matching_paren (bool flag)
+{
+  rl_blink_matching_paren = flag ? 1 : 0;
+}
+
+void
+gnu_readline::do_set_paren_string_delimiters (const string& s)
+{
+  static char *ss = 0;
+
+  delete [] ss;
+
+  ss = strsave (s.c_str ());
+
+  rl_paren_string_delimiters = ss;
+}
+
+void
+gnu_readline::do_set_completion_append_character (char c)
+{
+  rl_completion_append_character = c;
+}
+
+void
+gnu_readline::do_set_attempted_completion_function (fcn f)
+{
+  attempted_completion_function = f;
+}
+
+void
+gnu_readline::do_insert_text (const string& text)
+{
+  rl_insert_text (text.c_str ());
+}
+
+void
+gnu_readline::do_newline (void)
+{
+  rl_newline ();
+}
+
+void
+gnu_readline::do_clear_undo_list ()
+{
+  if (rl_undo_list)
+    {
+      free_undo_list ();
+
+      rl_undo_list = 0;
+    }
+}
+
+void
+gnu_readline::do_set_startup_hook (fcn f)
+{
+  previous_startup_hook = rl_startup_hook;
+
+  rl_startup_hook = f;
+}
+
+void
+gnu_readline::do_restore_startup_hook (void)
+{
+  rl_startup_hook = previous_startup_hook;
+}
+
+void
+gnu_readline::operate_and_get_next (int /* count */, int /* c */)
+{
+  // Accept the current line.
+
+  command_editor::newline ();
+
+  // Find the current line, and find the next line to use.
+
+  int x_where = command_history::where ();
+
+  int x_length = command_history::length ();
+
+  if ((command_history::is_stifled ()
+       && (x_length >= command_history::max_input_history ()))
+      || (x_where >= x_length - 1))
+    command_history::set_mark (x_where);
+  else
+    command_history::set_mark (x_where + 1);
+
+  command_editor::set_startup_hook (command_history::goto_mark);
+}
+
+#endif
+
+class
+default_command_editor : public command_editor
+{
+public:
+
+  default_command_editor (void)
+    : command_editor (), input_stream (stdin), output_stream (stdout) { }
+
+  ~default_command_editor (void) { }
+
+  string do_readline (const string& prompt);
+
+  void do_set_input_stream (FILE *f);
+
+  FILE *do_get_input_stream (void);
+
+  void do_set_output_stream (FILE *f);
+
+  FILE *do_get_output_stream (void);
+
+  void do_insert_text (const string&);
+
+  void do_newline (void);
+
+private:
+
+  FILE *input_stream;
+
+  FILE *output_stream;
+};
+
+string
+default_command_editor::do_readline (const string& prompt)
+{
+  fprintf (output_stream, prompt.c_str ());
+  fflush (output_stream);
+
+  return octave_fgets (input_stream);
+}
+
+void
+default_command_editor::do_set_input_stream (FILE *f)
+{
+  input_stream = f;
+}
+
+FILE *
+default_command_editor::do_get_input_stream (void)
+{
+  return input_stream;
+}
+
+void
+default_command_editor::do_set_output_stream (FILE *f)
+{
+  output_stream = f;
+}
+
+FILE *
+default_command_editor::do_get_output_stream (void)
+{
+  return output_stream;
+}
+
+void
+default_command_editor::do_insert_text (const string&)
+{
+  // XXX FIXME XXX
+}
+
+void
+default_command_editor::do_newline (void)
+{
+  // XXX FIXME XXX
+}
+
+bool
+command_editor::instance_ok (void)
+{
+  bool retval = true;
+
+  if (! instance)
+    make_command_editor ();
+
+  if (! instance)
+    {
+      (*current_liboctave_error_handler)
+	("unable to create command history object!");
+
+      retval = false;
+    }
+
+  return retval;
+}
+
+void
+command_editor::make_command_editor (void)
+{
+#if defined (USE_READLINE)
+  instance = new gnu_readline ();
+#else
+  instance = new default_command_editor ();
+#endif
+}
+
+void
+command_editor::set_name (const string& n)
+{
+  if (instance_ok ())
+    instance->do_set_name (n);
+}
+
+string
+command_editor::readline (const string& prompt)
+{
+  return (instance_ok ())
+    ? instance->do_readline (prompt) : string ();
+}
+
+void
+command_editor::set_input_stream (FILE *f)
+{
+  if (instance_ok ())
+    instance->do_set_input_stream (f);
+}
+
+FILE *
+command_editor::get_input_stream (void)
+{
+  return (instance_ok ())
+    ? instance->do_get_input_stream () : 0;
+}
+
+void
+command_editor::set_output_stream (FILE *f)
+{
+  if (instance_ok ())
+    instance->do_set_output_stream (f);
+}
+
+FILE *
+command_editor::get_output_stream (void)
+{
+  return (instance_ok ())
+    ? instance->do_get_output_stream () : 0;
+}
+
+int
+command_editor::terminal_rows (void)
+{
+  return (instance_ok ())
+    ? instance->do_terminal_rows () : -1;
+}
+
+int
+command_editor::terminal_cols (void)
+{
+  return (instance_ok ())
+    ? instance->do_terminal_cols () : -1;
+}
+
+void
+command_editor::clear_screen (void)
+{
+  if (instance_ok ())
+    instance->do_clear_screen ();
+}
+
+string
+command_editor::decode_prompt_string (const string& s)
+{
+  return (instance_ok ())
+    ? instance->do_decode_prompt_string (s) : string ();
+}
+
+int
+command_editor::current_command_number (void)
+{
+  return (instance_ok ())
+    ? instance->command_number : 0;
+}
+
+void
+command_editor::reset_current_command_number (int n)
+{
+  if (instance_ok ())
+    instance->command_number = n;
+}
+
+void
+command_editor::restore_terminal_state (void)
+{
+  if (instance_ok ())
+    instance->do_restore_terminal_state ();
+}
+
+void
+command_editor::blink_matching_paren (bool flag)
+{
+  if (instance_ok ())
+    instance->do_blink_matching_paren (flag);
+}
+
+void
+command_editor::set_paren_string_delimiters (const string& s)
+{
+  if (instance_ok ())
+    instance->do_set_paren_string_delimiters (s);
+}
+
+void
+command_editor::set_completion_append_character (char c)
+{
+  if (instance_ok ())
+    instance->do_set_completion_append_character (c);
+}
+
+void
+command_editor::set_attempted_completion_function (fcn f)
+{
+  if (instance_ok ())
+    instance->do_set_attempted_completion_function (f);
+}
+
+void
+command_editor::insert_text (const string& text)
+{
+  if (instance_ok ())
+    instance->do_insert_text (text);
+}
+
+void
+command_editor::newline (void)
+{
+  if (instance_ok ())
+    instance->do_newline ();
+}
+
+void
+command_editor::clear_undo_list (void)
+{
+  if (instance_ok ())
+    instance->do_clear_undo_list ();
+}
+
+void
+command_editor::set_startup_hook (fcn f)
+{
+  if (instance_ok ())
+    instance->do_set_startup_hook (f);
+}
+
+void
+command_editor::restore_startup_hook (void)
+{
+  if (instance_ok ())
+    instance->do_restore_startup_hook ();
+}
+
+// Return a string which will be printed as a prompt.  The string may
+// contain special characters which are decoded as follows: 
+//   
+//	\t	the time
+//	\d	the date
+//	\n	CRLF
+//	\s	the name of the shell (program)
+//	\w	the current working directory
+//	\W	the last element of PWD
+//	\u	your username
+//	\h	the hostname
+//	\#	the command number of this command
+//	\!	the history number of this command
+//	\$	a $ or a # if you are root
+//	\<octal> character code in octal
+//	\\	a backslash
+
+string
+command_editor::do_decode_prompt_string (const string& s)
+{
+  string result;
+  string temp;
+  size_t i = 0;
+  size_t slen = s.length ();
+  int c;
+
+  while (i < slen)
+    {
+      c = s[i];
+
+      i++;
+
+      if (c == '\\')
+	{
+	  c = s[i];
+
+	  switch (c)
+	    {
+	    case '0':
+	    case '1':
+	    case '2':
+	    case '3':
+	    case '4':
+	    case '5':
+	    case '6':
+	    case '7':
+	      // Maybe convert an octal number.
+	      {
+		int n = read_octal (s.substr (i, 3));
+
+		temp = "\\";
+
+		if (n != -1)
+		  {
+		    i += 3;
+		    temp[0] = n;
+		  }
+
+		c = 0;
+		goto add_string;
+	      }
+	  
+	    case 't':
+	    case 'd':
+	      // Make the current time/date into a string.
+	      {
+		time_t now = time (0);
+
+		temp = ctime (&now);
+
+		if (c == 't')
+		  {
+		    temp = temp.substr (11);
+		    temp.resize (8);
+		  }
+		else
+		  temp.resize (10);
+
+		goto add_string;
+	      }
+
+	    case 'n':
+	      {
+		temp = newline_chars ();
+
+		goto add_string;
+	      }
+
+	    case 's':
+	      {
+		temp = octave_env::get_program_name ();
+		temp = octave_env::base_pathname (temp);
+
+		goto add_string;
+	      }
+	
+	    case 'w':
+	    case 'W':
+	      {
+		temp = octave_env::getcwd ();
+
+		if (c == 'W')
+		  {
+		    size_t pos = temp.rfind ('/');
+
+		    if (pos != NPOS && pos != 0)
+		      temp = temp.substr (pos + 1);
+		  }
+		else
+		  temp = octave_env::polite_directory_format (temp);
+
+		goto add_string;
+	      }
+      
+	    case 'u':
+	      {
+		temp = octave_env::get_user_name ();
+
+		goto add_string;
+	      }
+
+	    case 'H':
+	      {
+		temp = octave_env::get_host_name ();
+
+		goto add_string;
+	      }
+
+	    case 'h':
+	      {
+		temp = octave_env::get_host_name ();
+
+		size_t pos = temp.find ('.');
+
+		if (pos != NPOS)
+		  temp.resize (pos);
+		
+		goto add_string;
+	      }
+
+	    case '#':
+	      {
+		char number_buffer[128];
+		sprintf (number_buffer, "%d", command_number);
+		temp = number_buffer;
+
+		goto add_string;
+	      }
+
+	    case '!':
+	      {
+		char number_buffer[128];
+		int num = command_history::current_number ();
+		if (num > 0)
+                  sprintf (number_buffer, "%d", num);
+		else
+		  strcpy (number_buffer, "!");
+		temp = number_buffer;
+
+		goto add_string;
+	      }
+
+	    case '$':
+	      {
+		temp = (::geteuid () == 0 ? "#" : "$");
+
+		goto add_string;
+	      }
+
+#if defined (USE_READLINE)
+	    case '[':
+	    case ']':
+	      {
+		temp.resize (2);
+
+		temp[0] = '\001';
+		temp[1] = ((c == '[')
+			   ? RL_PROMPT_START_IGNORE
+			   : RL_PROMPT_END_IGNORE);
+
+		goto add_string;
+	      }
+#endif
+
+	    case '\\':
+	      {
+		temp = "\\";
+
+		goto add_string;
+	      }
+
+	    default:
+	      {
+		temp = "\\ ";
+		temp[1] = c;
+
+		goto add_string;
+	      }
+
+	    add_string:
+	      {
+		if (c)
+		  i++;
+
+		result.append (temp);
+
+		break;
+	      }
+	    }
+	}
+      else
+	result += c;
+    }
+
+  return result;
+}
+
+// Return the octal number parsed from STRING, or -1 to indicate that
+// the string contained a bad number.
+
+int
+command_editor::read_octal (const string& s)
+{
+  int result = 0;
+  int digits = 0;
+
+  size_t i = 0;
+  size_t slen = s.length ();
+
+  while (i < slen && s[i] >= '0' && s[i] < '8')
+    {
+      digits++;
+      result = (result * 8) + s[i] - '0';
+      i++;
+    }
+
+  if (! digits || result > 0777 || i < slen)
+    result = -1;
+
+  return result;
+}
+
+void
+command_editor::error (int err_num)
+{
+  (*current_liboctave_error_handler) ("%s", strerror (err_num));
+}
+
+void
+command_editor::error (const string& s)
+{
+  (*current_liboctave_error_handler) ("%s", s.c_str ());
+}
+
+/*
+;;; Local Variables: ***
+;;; mode: C++ ***
+;;; End: ***
+*/
new file mode 100644
--- /dev/null
+++ b/liboctave/cmd-edit.h
@@ -0,0 +1,167 @@
+/*
+
+Copyright (C) 1996, 1997 John W. Eaton
+
+This file is part of Octave.
+
+Octave is free software; you can redistribute it and/or modify it
+under the terms of the GNU General Public License as published by the
+Free Software Foundation; either version 2, or (at your option) any
+later version.
+
+Octave is distributed in the hope that it will be useful, but WITHOUT
+ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+for more details.
+
+You should have received a copy of the GNU General Public License
+along with Octave; see the file COPYING.  If not, write to the Free
+Software Foundation, 59 Temple Place - Suite 330, Boston, MA  02111-1307, USA.
+
+*/
+
+#if !defined (octave_cmd_edit_h)
+#define octave_cmd_edit_h 1
+
+#include <cstdio>
+
+#include <string>
+
+class
+command_editor
+{
+protected:
+
+  command_editor (void)
+    : command_number (0) { }
+
+public:
+
+  typedef int (*fcn) (...);
+
+  virtual ~command_editor (void) { }
+
+  static void set_name (const string& n);
+
+  static string readline (const string& prompt);
+
+  static void set_input_stream (FILE *f);
+
+  static FILE *get_input_stream (void);
+
+  static void set_output_stream (FILE *f);
+
+  static FILE *get_output_stream (void);
+
+  static int terminal_rows (void);
+
+  static int terminal_cols (void);
+
+  static void clear_screen (void);
+
+  static string decode_prompt_string (const string& s);
+
+  static void restore_terminal_state (void);
+
+  static void blink_matching_paren (bool flag);
+
+  static void set_paren_string_delimiters (const string& s);
+
+  static void set_completion_append_character (char c);
+
+  static void set_attempted_completion_function (fcn f);
+
+  static void insert_text (const string& text);
+
+  static void newline (void);
+
+  static void clear_undo_list (void);
+
+  static void set_startup_hook (fcn f);
+
+  static void restore_startup_hook (void);
+
+  static int current_command_number (void);
+
+  static void reset_current_command_number (int n);
+
+private:
+
+  // No copying!
+
+  command_editor (const command_editor&);
+
+  command_editor& operator = (const command_editor&);
+
+  static bool instance_ok (void);
+
+  static void make_command_editor (void);
+
+  // The real thing.
+  static command_editor *instance;
+
+protected:
+
+  // To use something other than the GNU readline library, derive a new
+  // class from command_editor, overload these functions as
+  // necessary, and make instance point to the new class.
+
+  virtual void do_set_name (const string&) { }
+
+  virtual string do_readline (const string&) = 0;
+
+  virtual void do_set_input_stream (FILE *) = 0;
+
+  virtual FILE *do_get_input_stream (void) = 0;
+
+  virtual void do_set_output_stream (FILE *) = 0;
+
+  virtual FILE *do_get_output_stream (void) = 0;
+
+  virtual int do_terminal_rows (void) { return 24; }
+
+  virtual int do_terminal_cols (void) { return 80; }
+
+  virtual void do_clear_screen (void) { }
+
+  virtual string do_decode_prompt_string (const string&);
+
+  virtual string newline_chars (void) { return "\n"; } 
+
+  virtual void do_restore_terminal_state (void) { }
+
+  virtual void do_blink_matching_paren (bool) { }
+
+  virtual void do_set_paren_string_delimiters (const string&) { }
+
+  virtual void do_set_completion_append_character (char) { }
+
+  virtual void do_set_attempted_completion_function (fcn) { }
+
+  virtual void do_insert_text (const string&) = 0;
+
+  virtual void do_newline (void) = 0;
+
+  virtual void do_clear_undo_list (void) { }
+
+  virtual void do_set_startup_hook (fcn) { }
+
+  virtual void do_restore_startup_hook (void) { }
+
+  int read_octal (const string& s);
+
+  void error (int);
+
+  void error (const string&);
+
+  // The current command number.
+  int command_number;
+};
+
+#endif
+
+/*
+;;; Local Variables: ***
+;;; mode: C++ ***
+;;; End: ***
+*/
--- a/liboctave/cmd-hist.cc
+++ b/liboctave/cmd-hist.cc
@@ -26,6 +26,19 @@
 
 #include <cstring>
 
+#include <string>
+
+#include "cmd-edit.h"
+#include "cmd-hist.h"
+#include "lo-error.h"
+#include "str-vec.h"
+
+command_history *command_history::instance = 0;
+
+#if defined (USE_READLINE)
+
+#include <cstdlib>
+
 #include <strstream.h>
 
 #ifdef HAVE_FCNTL_H
@@ -41,95 +54,82 @@
 
 #include <readline/history.h>
 
-#include "file-ops.h"
-#include "lo-error.h"
-#include "cmd-hist.h"
+#include "file-stat.h"
 
-bool command_history::initialized = false;
-
-command_history::command_history (const string& f, int n)
+class
+gnu_history : public command_history
 {
-  if (initialized)
-    error ("only one history object can be active at once");
-  else
-    {
-      ignoring_additions = false;
+public:
+
+  gnu_history (void)
+    : command_history (), mark (0) { }
+
+  ~gnu_history (void) { }
+
+  void do_add (const string&);
+
+  void do_remove (int);
 
-      lines_in_file = 0;
-      lines_this_session = 0;
+  int do_where (void);
+
+  int do_length (void);
+
+  int do_max_input_history (void);
+
+  int do_base (void);
+
+  int do_current_number (void);
+
+  void do_stifle (int);
 
-      xsize = -1;
+  int do_unstifle (void);
+
+  int do_is_stifled (void);
+
+  void do_set_mark (int);
 
-      if (! f.empty ())
-	{
-	  xfile = f;
+  void do_goto_mark (void);
+
+  void do_read (const string&, bool);
 
-	  ::read_history (f.c_str ());
+  void do_read_range (const string&, int, int, bool);
 
-	  lines_in_file = where ();
+  void do_write (const string&);
 
-	  ::using_history ();
-	}
+  void do_append (const string&);
+
+  void do_truncate_file (const string&, int);
+
+  string_vector do_list (int, bool);
+
+  string do_get_entry (int);
 
-      if (n > 0)
-	xsize = n;
+  void do_replace_entry (int, const string&);
+
+  void do_clean_up_and_save (const string&, int);
 
-      initialized = true;
-    }
-}
+private:
+
+  int mark;
+};
 
 void
-command_history::set_file (const string& f)
-{
-  xfile = f;
-}
-
-string
-command_history::file (void)
-{
-  return xfile;
-}
-
-void
-command_history::set_size (int n)
-{
-  xsize = n;
-}
-
-int
-command_history::size (void)
+gnu_history::do_add (const string& s)
 {
-  return xsize;
-}
-
-void
-command_history::ignore_entries (bool flag)
-{
-  ignoring_additions = flag;
-}
-
-bool
-command_history::ignoring_entries (void)
-{
-  return ignoring_additions;
-}
-
-void
-command_history::add (const string& s)
-{
-  if (! ignoring_entries ())
+  if (! do_ignoring_entries ())
     {
       if (s.empty ()
 	  || (s.length () == 1 && (s[0] == '\r' || s[0] == '\n')))
 	return;
 
       ::add_history (s.c_str ());
+
       lines_this_session++;
     }
 }
 
 void
-command_history::remove (int n)
+gnu_history::do_remove (int n)
 {
   HIST_ENTRY *discard = ::remove_history (n);
 
@@ -143,49 +143,87 @@
 }
 
 int
-command_history::where (void)
+gnu_history::do_where (void)
 {
   return ::where_history ();
 }
 
 int
-command_history::base (void)
+gnu_history::do_length (void)
+{
+  return ::history_length;
+}
+
+int
+gnu_history::do_max_input_history (void)
+{
+  return ::max_input_history;
+}
+
+int
+gnu_history::do_base (void)
 {
   return ::history_base;
 }
 
 int
-command_history::current_number (void)
+gnu_history::do_current_number (void)
 {
-  return (xsize > 0) ? base () + where () : -1;
+  return (xsize > 0) ? do_base () + do_where () : -1;
 }
 
 void
-command_history::stifle (int n)
+gnu_history::do_stifle (int n)
 {
   ::stifle_history (n);
 }
 
 int
-command_history::unstifle (void)
+gnu_history::do_unstifle (void)
 {
   return ::unstifle_history ();
 }
 
 int
-command_history::is_stifled (void)
+gnu_history::do_is_stifled (void)
 {
   return ::history_is_stifled ();
 }
 
 void
-command_history::read (bool must_exist)
+gnu_history::do_set_mark (int n)
 {
-  read (xfile, must_exist);
+  mark = n;
 }
 
 void
-command_history::read (const string& f, bool must_exist)
+gnu_history::do_goto_mark (void)
+{
+  HIST_ENTRY *h;
+
+  if (mark)
+    {
+      if (history_set_pos (mark))
+	{
+	  h = ::current_history ();
+
+	  if (h)
+	    {
+	      command_editor::insert_text (h->line);
+
+	      command_editor::clear_undo_list ();
+	    }
+	}
+    }
+
+  mark = 0;
+
+  // XXX FIXME XXX -- for operate_and_get_next.
+  command_editor::restore_startup_hook ();
+}
+
+void
+gnu_history::do_read (const string& f, bool must_exist)
 {
   if (! f.empty ())
     {
@@ -195,24 +233,18 @@
 	error (status);
       else
 	{
-	  lines_in_file = where ();
+	  lines_in_file = do_where ();
 
 	  ::using_history ();
 	}
     }
   else
-    error ("command_history::read: missing file name");
+    error ("gnu_history::read: missing file name");
 }
 
 void
-command_history::read_range (int from, int to, bool must_exist)
-{
-  read_range (xfile, from, to, must_exist);
-}
-
-void
-command_history::read_range (const string& f, int from, int to,
-			     bool must_exist)
+gnu_history::do_read_range (const string& f, int from, int to,
+			    bool must_exist)
 {
   if (from < 0)
     from = lines_in_file;
@@ -225,17 +257,17 @@
 	error (status);
       else
 	{
-	  lines_in_file = where ();
+	  lines_in_file = do_where ();
 
 	  ::using_history ();
 	}
     }
   else
-    error ("command_history::read_range: missing file name");
+    error ("gnu_history::read_range: missing file name");
 }
 
 void
-command_history::write (const string& f_arg)
+gnu_history::do_write (const string& f_arg)
 {
   string f = f_arg;
 
@@ -250,15 +282,15 @@
 	error (status);
     }
   else
-    error ("command_history::write: missing file name");
+    error ("gnu_history::write: missing file name");
 }
 
 void
-command_history::append (const string& f_arg)
+gnu_history::do_append (const string& f_arg)
 {
   if (lines_this_session)
     {
-      if (lines_this_session < where ())
+      if (lines_this_session < do_where ())
 	{
 	  // Create file if it doesn't already exist.
 
@@ -289,13 +321,13 @@
 	      lines_this_session = 0;
 	    }
 	  else
-	    error ("comman_history::append: missing file name");
+	    error ("gnu_history::append: missing file name");
 	}
     }
 }
 
 void
-command_history::truncate_file (const string& f_arg, int n)
+gnu_history::do_truncate_file (const string& f_arg, int n)
 {
   string f = f_arg;
 
@@ -305,11 +337,11 @@
   if (! f.empty ())
     ::history_truncate_file (f.c_str (), n);
   else
-    error ("command_history::truncate_file: missing file name");
+    error ("gnu_history::truncate_file: missing file name");
 }
 
 string_vector
-command_history::list (int limit, int number_lines)
+gnu_history::do_list (int limit, bool number_lines)
 {
   string_vector retval;
 
@@ -333,7 +365,7 @@
 	      ostrstream output_buf;
 
 	      if (number_lines)
-		output_buf.form ("%5d%c", i + ::history_base,
+		output_buf.form ("%5d%c", i + do_base (),
 				 hlist[i]->data ? '*' : ' '); 
 
 	      output_buf << hlist[i]->line << ends;
@@ -351,11 +383,11 @@
 }
 
 string
-command_history::get_entry (int n)
+gnu_history::do_get_entry (int n)
 {
   string retval;
 
-  HIST_ENTRY *entry = ::history_get (::history_base + n);
+  HIST_ENTRY *entry = ::history_get (do_base () + n);
 
   if (entry && entry->line)
     retval = entry->line;
@@ -364,7 +396,7 @@
 }
 
 void
-command_history::replace_entry (int which, const string& line)
+gnu_history::do_replace_entry (int which, const string& line)
 {
   HIST_ENTRY *discard = ::replace_history_entry (which, line.c_str (), 0);
 
@@ -378,7 +410,7 @@
 }
 
 void
-command_history::clean_up_and_save (const string& f_arg, int n)
+gnu_history::do_clean_up_and_save (const string& f_arg, int n)
 {
   string f = f_arg;
 
@@ -392,9 +424,448 @@
 
       stifle (n);
 
-      ::write_history (f.c_str ());
+      do_write (f.c_str ());
     }
   else
+    error ("gnu_history::clean_up_and_save: missing file name");
+}
+
+#endif
+
+bool
+command_history::instance_ok (void)
+{
+  bool retval = true;
+
+  if (! instance)
+    make_command_history ();
+
+  if (! instance)
+    {
+      (*current_liboctave_error_handler)
+	("unable to create command history object!");
+
+      retval = false;
+    }
+
+  return retval;
+}
+
+void
+command_history::make_command_history (void)
+{
+#if defined (USE_READLINE)
+  instance = new gnu_history ();
+#else
+  instance = new command_history ();
+#endif
+}
+
+void
+command_history::set_file (const string& f)
+{
+  if (instance_ok ())
+    instance->do_set_file (f);
+}
+
+string
+command_history::file (void)
+{
+  return (instance_ok ())
+    ? instance->do_file () : string ();
+}
+
+void
+command_history::set_size (int n)
+{
+  if (instance_ok ())
+    instance->do_set_size (n);
+}
+
+int
+command_history::size (void)
+{
+  return (instance_ok ())
+    ? instance->do_size () : 0;
+}
+
+void
+command_history::ignore_entries (bool flag)
+{
+  if (instance_ok ())
+    instance->do_ignore_entries (flag);
+}
+
+bool
+command_history::ignoring_entries (void)
+{
+  return (instance_ok ())
+    ? instance->do_ignoring_entries () : false;
+}
+
+void
+command_history::add (const string& s)
+{
+  if (instance_ok ())
+    instance->do_add (s);
+}
+
+void
+command_history::remove (int n)
+{
+  if (instance_ok ())
+    instance->do_remove (n);
+}
+
+int
+command_history::where (void)
+{
+  return (instance_ok ())
+    ? instance->do_where () : 0;
+}
+
+int
+command_history::length (void)
+{
+  return (instance_ok ())
+    ? instance->do_length () : 0;
+}
+
+int
+command_history::max_input_history (void)
+{
+  return (instance_ok ())
+    ? instance->do_max_input_history () : 0;
+}
+
+int
+command_history::base (void)
+{
+  return (instance_ok ())
+    ? instance->do_base () : 0;
+}
+
+int
+command_history::current_number (void)
+{
+  return (instance_ok ())
+    ? instance->do_current_number () : 0;
+}
+
+void
+command_history::stifle (int n)
+{
+  if (instance_ok ())
+    instance->do_stifle (n);
+}
+
+int
+command_history::unstifle (void)
+{
+  return (instance_ok ())
+    ? instance->do_unstifle () : 0;
+}
+
+int
+command_history::is_stifled (void)
+{
+  return (instance_ok ())
+    ? instance->do_is_stifled () : 0;
+}
+
+void
+command_history::set_mark (int n)
+{
+  if (instance_ok ())
+    instance->do_set_mark (n);
+}
+
+int
+command_history::goto_mark (...)
+{
+  if (instance_ok ())
+    instance->do_goto_mark ();
+
+  return 0;
+}
+
+void
+command_history::read (bool must_exist)
+{
+  if (instance_ok ())
+    instance->do_read (must_exist);
+}
+
+void
+command_history::read (const string& f, bool must_exist)
+{
+  if (instance_ok ())
+    instance->do_read (f, must_exist);
+}
+
+void
+command_history::read_range (int from, int to, bool must_exist)
+{
+  if (instance_ok ())
+    instance->do_read_range (from, to, must_exist);
+}
+
+void
+command_history::read_range (const string& f, int from, int to,
+			     bool must_exist) 
+{
+  if (instance_ok ())
+    instance->do_read_range (f, from, to, must_exist);
+}
+
+void
+command_history::write (const string& f)
+{
+  if (instance_ok ())
+    instance->do_write (f);
+}
+
+void
+command_history::append (const string& f)
+{
+  if (instance_ok ())
+    instance->do_append (f);
+}
+
+void
+command_history::truncate_file (const string& f, int n)
+{
+  if (instance_ok ())
+    instance->do_truncate_file (f, n);
+}
+
+string_vector
+command_history::list (int limit, bool number_lines)
+{
+  return (instance_ok ())
+    ? instance->do_list (limit, number_lines) : string_vector ();
+}
+
+string
+command_history::get_entry (int n)
+{
+  return (instance_ok ())
+    ? instance->do_get_entry (n) : string ();
+}
+
+void
+command_history::replace_entry (int which, const string& line)
+{
+  if (instance_ok ())
+    instance->do_replace_entry (which, line);
+}
+
+void
+command_history::clean_up_and_save (const string& f, int n)
+{
+  if (instance_ok ())
+    instance->do_clean_up_and_save (f, n);
+}
+
+void
+command_history::do_set_file (const string& f)
+{
+  xfile = f;
+}
+
+string
+command_history::do_file (void)
+{
+  return xfile;
+}
+
+void
+command_history::do_set_size (int n)
+{
+  xsize = n;
+}
+
+int
+command_history::do_size (void)
+{
+  return xsize;
+}
+
+void
+command_history::do_ignore_entries (bool flag)
+{
+  ignoring_additions = flag;
+}
+
+bool
+command_history::do_ignoring_entries (void)
+{
+  return ignoring_additions;
+}
+
+void
+command_history::do_add (const string&)
+{
+}
+
+void
+command_history::do_remove (int)
+{
+}
+
+int
+command_history::do_where (void)
+{
+  return 0;
+}
+
+int
+command_history::do_length (void)
+{
+  return 0;
+}
+
+int
+command_history::do_max_input_history (void)
+{
+  return 0;
+}
+
+int
+command_history::do_base (void)
+{
+  return 0;
+}
+
+int
+command_history::do_current_number (void)
+{
+  return (xsize > 0) ? do_base () + do_where () : -1;
+}
+
+void
+command_history::do_stifle (int)
+{
+}
+
+int
+command_history::do_unstifle (void)
+{
+  return -1;
+}
+
+int
+command_history::do_is_stifled (void)
+{
+  return 0;
+}
+
+void
+command_history::do_set_mark (int)
+{
+}
+
+void
+command_history::do_goto_mark (void)
+{
+}
+
+void
+command_history::do_read (bool must_exist)
+{
+  do_read (xfile, must_exist);
+}
+
+void
+command_history::do_read (const string& f, bool)
+{
+  if (f.empty ())
+    error ("command_history::read: missing file name");
+}
+
+void
+command_history::do_read_range (int from, int to, bool must_exist)
+{
+  do_read_range (xfile, from, to, must_exist);
+}
+
+void
+command_history::do_read_range (const string& f, int, int, bool)
+{
+  if (f.empty ())
+    error ("command_history::read_range: missing file name");
+}
+
+void
+command_history::do_write (const string& f_arg)
+{
+  string f = f_arg;
+
+  if (f.empty ())
+    f = xfile;
+
+  if (f.empty ())
+    error ("command_history::write: missing file name");
+}
+
+void
+command_history::do_append (const string& f_arg)
+{
+  if (lines_this_session)
+    {
+      if (lines_this_session < do_where ())
+	{
+	  // Create file if it doesn't already exist.
+
+	  string f = f_arg;
+
+	  if (f.empty ())
+	    f = xfile;
+
+	  if (f.empty ())
+	    error ("command_history::append: missing file name");
+	}
+    }
+}
+
+void
+command_history::do_truncate_file (const string& f_arg, int)
+{
+  string f = f_arg;
+
+  if (f.empty ())
+    f = xfile;
+
+  if (f.empty ())
+    error ("command_history::truncate_file: missing file name");
+}
+
+string_vector
+command_history::do_list (int, bool)
+{
+  return string_vector ();
+}
+
+string
+command_history::do_get_entry (int)
+{
+  return string ();
+}
+
+void
+command_history::do_replace_entry (int, const string&)
+{
+}
+
+void
+command_history::do_clean_up_and_save (const string& f_arg, int)
+{
+  string f = f_arg;
+
+  if (f.empty ())
+    f = xfile;
+
+  if (f.empty ())
     error ("command_history::clean_up_and_save: missing file name");
 }
 
--- a/liboctave/cmd-hist.h
+++ b/liboctave/cmd-hist.h
@@ -30,67 +30,160 @@
 class
 command_history
 {
+protected:
+
+  command_history (void)
+    : ignoring_additions (false), lines_in_file (0),
+      lines_this_session (0), xfile (), xsize (-1) { }
+
 public:
 
-  command_history (const string& = string (), int = -1);
+  virtual ~command_history (void) { }
+
+  static void set_file (const string&);
 
-  ~command_history (void) { initialized = false; }
+  static string file (void);
 
-  void set_file (const string&);
+  static void set_size (int);
 
-  string file (void);
+  static int size (void);
+
+  static void ignore_entries (bool = true);
 
-  void set_size (int);
+  static bool ignoring_entries (void);
 
-  int size (void);
+  static void add (const string&);
 
-  void ignore_entries (bool = true);
+  static void remove (int);
+
+  static int where (void);
 
-  bool ignoring_entries (void);
+  static int length (void);
 
-  void add (const string&);
+  static int max_input_history (void);
 
-  void remove (int);
+  static int base (void);
 
-  int where (void);
+  static int current_number (void);
 
-  int base (void);
+  static void stifle (int);
 
-  int current_number (void);
+  static int unstifle (void);
 
-  void stifle (int);
+  static int is_stifled (void);
 
-  int unstifle (void);
+  static void set_mark (int n);
 
-  int is_stifled (void);
+  // Gag.  This declaration has to match the Function typedef in
+  // readline.h.
 
-  void read (bool = true);
+  static int goto_mark (...);
+
+  static void read (bool = true);
 
-  void read (const string&, bool = true);
+  static void read (const string&, bool = true);
 
-  void read_range (int = -1, int = -1, bool = true);
+  static void read_range (int = -1, int = -1, bool = true);
 
-  void read_range (const string&, int = -1, int = -1,
-		   bool = true);
+  static void read_range (const string&, int = -1, int = -1,
+			  bool = true);
 
-  void write (const string& = string ());
+  static void write (const string& = string ());
 
-  void append (const string& = string ());
+  static void append (const string& = string ());
 
-  void truncate_file (const string& = string (), int = -1);
+  static void truncate_file (const string& = string (), int = -1);
 
-  string_vector list (int = -1, int = 0);
+  static string_vector list (int = -1, bool = false);
 
-  string get_entry (int);
+  static string get_entry (int);
 
-  void replace_entry (int, const string&);
+  static void replace_entry (int, const string&);
 
-  void clean_up_and_save (const string& = string (), int = -1);
+  static void clean_up_and_save (const string& = string (), int = -1);
 
 private:
 
-  // We can only have one history object in any given program.
-  static bool initialized;
+  // No copying!
+
+  command_history (const command_history&);
+
+  command_history& operator = (const command_history&);
+
+  static bool instance_ok (void);
+
+  static void make_command_history (void);
+
+  // The real thing.
+  static command_history *instance;
+
+protected:
+
+  // To use something other than the GNU history library, derive a new
+  // class from command_history, overload these functions as
+  // necessary, and make instance point to the new class.
+
+  virtual void do_set_file (const string&);
+
+  virtual string do_file (void);
+
+  virtual void do_set_size (int);
+
+  virtual int do_size (void);
+
+  virtual void do_ignore_entries (bool);
+
+  virtual bool do_ignoring_entries (void);
+
+  virtual void do_add (const string&);
+
+  virtual void do_remove (int);
+
+  virtual int do_where (void);
+
+  virtual int do_length (void);
+
+  virtual int do_max_input_history (void);
+
+  virtual int do_base (void);
+
+  virtual int do_current_number (void);
+
+  virtual void do_stifle (int);
+
+  virtual int do_unstifle (void);
+
+  virtual int do_is_stifled (void);
+
+  virtual void do_set_mark (int);
+
+  virtual void do_goto_mark (void);
+
+  virtual void do_read (bool);
+
+  virtual void do_read (const string&, bool);
+
+  virtual void do_read_range (int, int, bool);
+
+  virtual void do_read_range (const string&, int, int, bool);
+
+  virtual void do_write (const string&);
+
+  virtual void do_append (const string&);
+
+  virtual void do_truncate_file (const string&, int);
+
+  virtual string_vector do_list (int, bool);
+
+  virtual string do_get_entry (int);
+
+  virtual void do_replace_entry (int, const string&);
+
+  virtual void do_clean_up_and_save (const string&, int);
+
+  void error (int);
+
+  void error (const string&);
 
   // TRUE means we are ignoring new additions.
   bool ignoring_additions;
@@ -106,14 +199,6 @@
 
   // The number of lines of history to save.
   int xsize;
-
-  void error (int);
-
-  void error (const string&);
-
-  command_history (const command_history&);
-
-  command_history& operator = (const command_history&);
 };
 
 #endif
--- a/liboctave/dir-ops.cc
+++ b/liboctave/dir-ops.cc
@@ -25,11 +25,14 @@
 #endif
 
 #include <cerrno>
+#include <cstdlib>
 #include <cstring>
 
 #include "sysdir.h"
 
 #include "dir-ops.h"
+#include "lo-error.h"
+#include "lo-sysdep.h"
 #include "str-vec.h"
 
 bool
--- a/liboctave/file-ops.cc
+++ b/liboctave/file-ops.cc
@@ -29,224 +29,43 @@
 #include <cstdlib>
 #include <cstring>
 
-#ifdef HAVE_UNISTD_H
+#include <iostream.h>
+
 #ifdef HAVE_SYS_TYPES_H
 #include <sys/types.h>
 #endif
+
+#ifdef HAVE_UNISTD_H
 #include <unistd.h>
 #endif
 
-#include "error.h"
+#ifdef HAVE_PWD_H
+#include <pwd.h>
+#endif
+
 #include "file-ops.h"
 #include "lo-error.h"
+#include "oct-env.h"
 #include "statdefs.h"
-
-// These must come after <sys/types.h> and <sys/stat.h>.
-
-#include <safe-lstat.h>
-#include <safe-stat.h>
-
-// XXX FIXME XXX -- the is_* and mode_as_string functions are only valid
-// for initialized objects.  If called for an object that is not
-// initialized, they should throw an exception.
-
-bool
-file_stat::is_blk (void) const
-{
-#ifdef S_ISBLK
-  return S_ISBLK (fs_mode);
-#else
-  return false;
-#endif
-}
-
-bool
-file_stat::is_chr (void) const
-{
-#ifdef S_ISCHR
-  return S_ISCHR (fs_mode);
-#else
-  return false;
-#endif
-}
-
-bool
-file_stat::is_dir (void) const
-{ 
-#ifdef S_ISDIR
-  return S_ISDIR (fs_mode);
-#else
-  return false;
-#endif
-}
-
-bool
-file_stat::is_fifo (void) const
-{ 
-#ifdef S_ISFIFO
-  return S_ISFIFO (fs_mode);
-#else
-  return false;
-#endif
-}
-
-bool
-file_stat::is_lnk (void) const
-{ 
-#ifdef S_ISLNK
-  return S_ISLNK (fs_mode);
-#else
-  return false;
-#endif
-}
-
-bool
-file_stat::is_reg (void) const
-{ 
-#ifdef S_ISREG
-  return S_ISREG (fs_mode);
-#else
-  return false;
-#endif
-}
-
-bool
-file_stat::is_sock (void) const
-{ 
-#ifdef S_ISSOCK
-  return S_ISSOCK (fs_mode);
-#else
-  return false;
-#endif
-}
-
-extern "C" void mode_string ();
-
-string
-file_stat::mode_as_string (void) const
-{
-  char buf[11];
-
-  mode_string (fs_mode, buf);
-
-  buf[10] = '\0';
-
-  return string (buf);
-}
-
-// Private stuff:
-
-void
-file_stat::update_internal (bool force)
-{
-  if (! initialized || force)
-    {
-      initialized = false;
-      fail = false;
-
-      const char *cname = file_name.c_str ();
-
-      struct stat buf;
-
-      int status = follow_links
-	? SAFE_STAT (cname, &buf) : SAFE_LSTAT (cname, &buf);
-
-      if (status < 0)
-	{
-	  fail = true;
-	  errmsg = strerror (errno);
-	}
-      else
-	{
-	  fs_mode = buf.st_mode;
-	  fs_ino = buf.st_ino;
-	  fs_dev = buf.st_dev;
-	  fs_nlink = buf.st_nlink;
-	  fs_uid = buf.st_uid;
-	  fs_gid = buf.st_gid;
-	  fs_size = buf.st_size;
-	  fs_atime = buf.st_atime;
-	  fs_mtime = buf.st_mtime;
-	  fs_ctime = buf.st_ctime;
-
-#if defined (HAVE_ST_RDEV)
-	  fs_rdev = buf.st_rdev;
-#endif
-
-#if defined (HAVE_ST_BLKSIZE)
-	  fs_blksize = buf.st_blksize;
-#endif
-
-#if defined (HAVE_ST_BLOCKS)
-	  fs_blocks = buf.st_blocks;
-#endif
-	}
-
-      initialized = true;
-    }
-}
-
-void
-file_stat::copy (const file_stat& fs)
-{
-  file_name = fs.file_name;
-  follow_links = fs.follow_links;
-  initialized = fs.initialized;
-  fail = fs.fail;
-  errmsg = fs.errmsg;
-  fs_mode = fs.fs_mode;
-  fs_ino = fs.fs_ino;
-  fs_dev = fs.fs_dev;
-  fs_nlink = fs.fs_nlink;
-  fs_uid = fs.fs_uid;
-  fs_gid = fs.fs_gid;
-  fs_size = fs.fs_size;
-  fs_atime = fs.fs_atime;
-  fs_mtime = fs.fs_mtime;
-  fs_ctime = fs.fs_ctime;
-
-#if defined (HAVE_ST_RDEV)
-  fs_rdev = fs.fs_rdev;
-#endif
-
-#if defined (HAVE_ST_BLKSIZE)
-  fs_blksize = fs.fs_blksize;
-#endif
-
-#if defined (HAVE_ST_BLOCKS)
-  fs_blocks = fs.fs_blocks;
-#endif
-}
-
-// Functions for octave.
-
-// Has FILE been modified since TIME?  Returns 1 for yes, 0 for no,
-// and -1 for any error.
-int
-is_newer (const string& file, time_t time)
-{
-  file_stat fs (file);
-
-  return fs ? fs.is_newer (time) : -1;
-}
+#include "str-vec.h"
 
 // We provide a replacement for mkdir().
 
 int
-oct_mkdir (const string& name, mode_t mode)
+file_ops::mkdir (const string& name, mode_t mode)
 {
-  return mkdir (name.c_str (), mode);
+  return ::mkdir (name.c_str (), mode);
 }
 
 int
-oct_mkdir (const string& name, mode_t mode, string& msg)
+file_ops::mkdir (const string& name, mode_t mode, string& msg)
 {
   msg = string ();
 
-  int status = mkdir (name.c_str (), mode);
+  int status = ::mkdir (name.c_str (), mode);
 
   if (status < 0)
-    msg = strerror (errno);
+    msg = ::strerror (errno);
 
   return status;
 }
@@ -254,30 +73,32 @@
 // I don't know how to emulate this on systems that don't provide it.
 
 int
-oct_mkfifo (const string& name, mode_t mode)
+file_ops::mkfifo (const string& name, mode_t mode)
 {
 #if defined (HAVE_MKFIFO)
-  return mkfifo (name.c_str (), mode);
+  return ::mkfifo (name.c_str (), mode);
 #else
-  ::error ("mkfifo: not implemented on this system");
+  (*current_liboctave_error_handler)
+    ("mkfifo: not implemented on this system");
   return -1;
 #endif
 }
 
 int
-oct_mkfifo (const string& name, mode_t mode, string& msg)
+file_ops::mkfifo (const string& name, mode_t mode, string& msg)
 {
   msg = string ();
 
 #if defined (HAVE_MKFIFO)
-  int status = mkfifo (name.c_str (), mode);
+  int status = ::mkfifo (name.c_str (), mode);
 
   if (status < 0)
-    msg = strerror (errno);
+    msg = ::strerror (errno);
 
   return status;
 #else
-  ::error ("mkfifo: not implemented on this system");
+  (*current_liboctave_error_handler)
+    ("mkfifo: not implemented on this system");
   return -1;
 #endif
 }
@@ -285,20 +106,20 @@
 // We provide a replacement for rename().
 
 int
-oct_rename (const string& from, const string& to)
+file_ops::rename (const string& from, const string& to)
 {
-  return rename (from.c_str (), to.c_str ());
+  return ::rename (from.c_str (), to.c_str ());
 }
 
 int
-oct_rename (const string& from, const string& to, string& msg)
+file_ops::rename (const string& from, const string& to, string& msg)
 {
   msg = string ();
 
-  int status = rename (from.c_str (), to.c_str ());
+  int status = ::rename (from.c_str (), to.c_str ());
 
   if (status < 0)
-    msg = strerror (errno);
+    msg = ::strerror (errno);
 
   return status;
 }
@@ -306,20 +127,20 @@
 // We provide a replacement for rmdir().
 
 int
-oct_rmdir (const string& name)
+file_ops::rmdir (const string& name)
 {
-  return rmdir (name.c_str ());
+  return ::rmdir (name.c_str ());
 }
 
 int
-oct_rmdir (const string& name, string& msg)
+file_ops::rmdir (const string& name, string& msg)
 {
   msg = string ();
 
-  int status = rmdir (name.c_str ());
+  int status = ::rmdir (name.c_str ());
 
   if (status < 0)
-    msg = strerror (errno);
+    msg = ::strerror (errno);
 
   return status;
 }
@@ -327,11 +148,11 @@
 // We provide a replacement for tempnam().
 
 string
-oct_tempnam (void)
+file_ops::tempnam (void)
 {
   string retval;
 
-  char *tmp = tempnam (0, "oct-");
+  char *tmp = ::tempnam (0, "oct-");
 
   if (tmp)
     {
@@ -345,32 +166,119 @@
   return retval;
 }
 
+// If NAME has a leading ~ or ~user, Unix-style, expand it to the
+// user's home directory.  If no ~, or no <pwd.h>, just return NAME.
+
+// Mostly stolen from kpathsea.  Readline also has a more complicated
+// tilde-expand function, but we can probalby get by with something a
+// bit simpler.
+
+// XXX FIXME XXX
+#define DIR_SEP_CHAR '/'
+
+string
+file_ops::tilde_expand (const string& name)
+{
+  string expansion = name;
+
+#if defined (HAVE_PWD_H)
+
+  // If no leading tilde, do nothing.
+
+  size_t beg = name.find_first_not_of (" \t");
+
+  if (beg != NPOS && name[beg] == '~')
+    {
+      // If `~' or `~/', use $HOME if it exists, or `.' if it doesn't.
+
+      // If `~user' or `~user/', look up user in the passwd database.
+
+      size_t len = name.length ();
+
+      if (beg == len-1 || name[beg+1] == DIR_SEP_CHAR)
+	{
+	  string home = octave_env::get_home_directory ();
+
+	  if (home.empty ())
+	    home = ".";
+        
+	  expansion = name.substr (0, beg) + home;
+
+	  if (beg < len)
+	    expansion.append (name.substr (beg+1));
+	}
+      else
+	{
+	  size_t end = name.find (DIR_SEP_CHAR, beg);
+
+	  size_t len = end;
+
+	  if (len != NPOS)
+	    len -= beg + 1;
+
+	  string user = name.substr (beg+1, len);
+
+	  struct passwd *p
+	    = static_cast<struct passwd *> (::getpwnam (user.c_str ()));
+
+	  // If no such user, just use `.'.
+
+	  string home = p ? p->pw_dir : ".";
+      
+	  expansion = string (" ", beg) + home;
+
+	  if (end != NPOS)
+	    expansion.append (name.substr (end));
+	}
+    }
+
+#endif
+
+  return expansion;
+}
+
+// A vector version of the above.
+
+string_vector
+file_ops::tilde_expand (const string_vector& names)
+{
+  string_vector retval;
+
+  int n = names.length ();
+
+  retval.resize (n);
+
+  for (int i = 0; i < n; i++)
+    retval[i] = file_ops::tilde_expand (names[i]);
+
+  return retval;
+}
 
 int
-oct_umask (mode_t mode)
+file_ops::umask (mode_t mode)
 {
 #if defined (HAVE_UMASK)
-  return umask (mode);
+  return ::umask (mode);
 #else
   return 0;
 #endif
 }
 
 int
-oct_unlink (const string& name)
+file_ops::unlink (const string& name)
 {
-  return unlink (name.c_str ());
+  return ::unlink (name.c_str ());
 }
 
 int
-oct_unlink (const string& name, string& errmsg)
+file_ops::unlink (const string& name, string& errmsg)
 {
   errmsg = string ();
 
-  int status = unlink (name.c_str ());
+  int status = ::unlink (name.c_str ());
 
   if (status < 0)
-    errmsg = strerror (errno);
+    errmsg = ::strerror (errno);
 
   return status;
 }
--- a/liboctave/file-ops.h
+++ b/liboctave/file-ops.h
@@ -25,192 +25,37 @@
 
 #include <string>
 
+class string_vector;
+
 #ifdef HAVE_SYS_TYPES_H
 #include <sys/types.h>
 #endif
 
-class
-file_stat
+struct
+file_ops
 {
-public:
-
-  file_stat (const string& n = string (), bool fl = true)
-    : file_name (n), follow_links (fl), initialized (false)
-      {
-	if (! file_name.empty ())
-	  update_internal ();
-      }
-
-  file_stat (const file_stat& f) { copy (f); }
-
-  file_stat& operator = (const file_stat& f)
-    {
-      if (this != &f)
-	copy (f);
-
-      return *this;
-    }
-
-  ~file_stat (void) { }
-
-  void get_stats (bool force = false)
-    {
-      if (! initialized || force)
-        update_internal (force);
-    }
-
-  void get_stats (const string& n, bool force = false)
-    {
-      if (n != file_name || ! initialized  || force)
-	{
-	  initialized = false;
-
-	  file_name = n;
-
-	  update_internal (force);
-	}
-    }
-
-  // File status and info.  These should only be called for objects
-  // that are already properly initialized.
+  static int mkdir (const string&, mode_t);
+  static int mkdir (const string&, mode_t, string&);
 
-  bool is_blk (void) const;
-  bool is_chr (void) const;
-  bool is_dir (void) const;
-  bool is_fifo (void) const;
-  bool is_lnk (void) const;
-  bool is_reg (void) const;
-  bool is_sock (void) const;
-
-  ino_t ino (void) const { return fs_ino; }
-  dev_t dev (void) const { return fs_dev; }
-
-  nlink_t nlink (void) const { return fs_nlink; }
-
-  uid_t uid (void) const { return fs_uid; }
-  gid_t gid (void) const { return fs_gid; }
-
-  off_t size (void) const { return fs_size; }
-
-  time_t atime (void) const { return fs_atime; }
-  time_t mtime (void) const { return fs_mtime; }
-  time_t ctime (void) const { return fs_ctime; }
+  static int mkfifo (const string&, mode_t);
+  static int mkfifo (const string&, mode_t, string&);
 
-#if defined (HAVE_ST_RDEV)
-  dev_t rdev (void) const { return fs_rdev; }
-#endif
-
-#if defined (HAVE_ST_BLKSIZE)
-  long blksize (void) const { return fs_blksize; }
-#endif
-
-#if defined (HAVE_ST_BLOCKS)
-  long blocks (void) const { return fs_blocks; }
-#endif
-
-  string mode_as_string (void) const;
-
-  bool ok (void) const { return initialized && ! fail; }
-
-  operator void* () const
-    { return ok ()
-	? static_cast<void *> (-1) : static_cast<void *> (0); }
-
-  bool exists (void) const { return ok (); }
-
-  string error (void) const { return ok () ? string () : errmsg; }
+  static int rename (const string&, const string&);
+  static int rename (const string&, const string&, string&);
 
-  // Has the file referenced by this object been modified since TIME?
-  bool is_newer (time_t time) const { return fs_mtime > time; }
-
-private:
-
-  // Name of the file.
-  string file_name;
-
-  // TRUE means follow symbolic links to the ultimate file (stat).
-  // FALSE means get information about the link itself (lstat).
-  bool follow_links;
-
-  // TRUE means we have already called stat.
-  bool initialized;
-
-  // TRUE means the stat for this file failed.
-  bool fail;
-
-  // If a failure occurs, this contains the system error text.
-  string errmsg;
+  static int rmdir (const string&);
+  static int rmdir (const string&, string&);
 
-  // file type and permissions
-  mode_t fs_mode;
-
-  // serial number
-  ino_t fs_ino;
-
-  // device number
-  dev_t fs_dev;
-
-  // number of links
-  nlink_t fs_nlink;
-
-  // user ID of owner
-  uid_t fs_uid;
-
-  // group ID of owner
-  gid_t fs_gid;
-
-  // size in bytes, for regular files
-  off_t fs_size;
-
-  // time of last access
-  time_t fs_atime;
+  static string tempnam (void);
 
-  // time of last modification
-  time_t fs_mtime;
-
-  // time of last file status change
-  time_t fs_ctime;
-
-#if defined (HAVE_ST_RDEV)
-  // device number for special files
-  dev_t fs_rdev;
-#endif
-
-#if defined (HAVE_ST_BLKSIZE)
-  // best I/O block size
-  long fs_blksize;
-#endif
-
-#if defined (HAVE_ST_BLOCKS)
-  // number of 512-byte blocks allocated
-  long fs_blocks;
-#endif
-
-  void update_internal (bool force = false);
+  static string tilde_expand (const string&);
+  static string_vector tilde_expand (const string_vector&);
 
-  void copy (const file_stat&);
-};
-
-extern int is_newer (const string&, time_t);
-
-extern int oct_mkdir (const string&, mode_t);
-extern int oct_mkdir (const string&, mode_t, string&);
-
-extern int oct_mkfifo (const string&, mode_t);
-extern int oct_mkfifo (const string&, mode_t, string&);
+  static int umask (mode_t);
 
-extern int oct_rename (const string&, const string&);
-extern int oct_rename (const string&, const string&, string&);
-
-extern int oct_rmdir (const string&);
-extern int oct_rmdir (const string&, string&);
-
-extern string oct_tempnam (void);
-
-extern int oct_umask (mode_t);
-
-extern int oct_unlink (const string&);
-extern int oct_unlink (const string&, string&);
+  static int unlink (const string&);
+  static int unlink (const string&, string&);
+};
 
 #endif
 
new file mode 100644
--- /dev/null
+++ b/liboctave/file-stat.cc
@@ -0,0 +1,232 @@
+/*
+
+Copyright (C) 1996, 1997 John W. Eaton
+
+This file is part of Octave.
+
+Octave is free software; you can redistribute it and/or modify it
+under the terms of the GNU General Public License as published by the
+Free Software Foundation; either version 2, or (at your option) any
+later version.
+
+Octave is distributed in the hope that it will be useful, but WITHOUT
+ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+for more details.
+
+You should have received a copy of the GNU General Public License
+along with Octave; see the file COPYING.  If not, write to the Free
+Software Foundation, 59 Temple Place - Suite 330, Boston, MA  02111-1307, USA.
+
+*/
+
+#ifdef HAVE_CONFIG_H
+#include <config.h>
+#endif
+
+#include <cerrno>
+#include <cstring>
+
+#ifdef HAVE_UNISTD_H
+#ifdef HAVE_SYS_TYPES_H
+#include <sys/types.h>
+#endif
+#include <unistd.h>
+#endif
+
+#include "file-stat.h"
+#include "statdefs.h"
+
+// These must come after <sys/types.h> and <sys/stat.h>.
+
+#include <safe-lstat.h>
+#include <safe-stat.h>
+
+// XXX FIXME XXX -- the is_* and mode_as_string functions are only valid
+// for initialized objects.  If called for an object that is not
+// initialized, they should throw an exception.
+
+bool
+file_stat::is_blk (void) const
+{
+#ifdef S_ISBLK
+  return S_ISBLK (fs_mode);
+#else
+  return false;
+#endif
+}
+
+bool
+file_stat::is_chr (void) const
+{
+#ifdef S_ISCHR
+  return S_ISCHR (fs_mode);
+#else
+  return false;
+#endif
+}
+
+bool
+file_stat::is_dir (void) const
+{ 
+#ifdef S_ISDIR
+  return S_ISDIR (fs_mode);
+#else
+  return false;
+#endif
+}
+
+bool
+file_stat::is_fifo (void) const
+{ 
+#ifdef S_ISFIFO
+  return S_ISFIFO (fs_mode);
+#else
+  return false;
+#endif
+}
+
+bool
+file_stat::is_lnk (void) const
+{ 
+#ifdef S_ISLNK
+  return S_ISLNK (fs_mode);
+#else
+  return false;
+#endif
+}
+
+bool
+file_stat::is_reg (void) const
+{ 
+#ifdef S_ISREG
+  return S_ISREG (fs_mode);
+#else
+  return false;
+#endif
+}
+
+bool
+file_stat::is_sock (void) const
+{ 
+#ifdef S_ISSOCK
+  return S_ISSOCK (fs_mode);
+#else
+  return false;
+#endif
+}
+
+extern "C" void mode_string ();
+
+string
+file_stat::mode_as_string (void) const
+{
+  char buf[11];
+
+  mode_string (fs_mode, buf);
+
+  buf[10] = '\0';
+
+  return string (buf);
+}
+
+// Has FILE been modified since TIME?  Returns 1 for yes, 0 for no,
+// and -1 for any error.
+
+int
+file_stat::is_newer (const string& file, time_t time)
+{
+  file_stat fs (file);
+
+  return fs ? fs.is_newer (time) : -1;
+}
+
+// Private stuff:
+
+void
+file_stat::update_internal (bool force)
+{
+  if (! initialized || force)
+    {
+      initialized = false;
+      fail = false;
+
+      const char *cname = file_name.c_str ();
+
+      struct stat buf;
+
+      int status = follow_links
+	? SAFE_STAT (cname, &buf) : SAFE_LSTAT (cname, &buf);
+
+      if (status < 0)
+	{
+	  fail = true;
+	  errmsg = strerror (errno);
+	}
+      else
+	{
+	  fs_mode = buf.st_mode;
+	  fs_ino = buf.st_ino;
+	  fs_dev = buf.st_dev;
+	  fs_nlink = buf.st_nlink;
+	  fs_uid = buf.st_uid;
+	  fs_gid = buf.st_gid;
+	  fs_size = buf.st_size;
+	  fs_atime = buf.st_atime;
+	  fs_mtime = buf.st_mtime;
+	  fs_ctime = buf.st_ctime;
+
+#if defined (HAVE_ST_RDEV)
+	  fs_rdev = buf.st_rdev;
+#endif
+
+#if defined (HAVE_ST_BLKSIZE)
+	  fs_blksize = buf.st_blksize;
+#endif
+
+#if defined (HAVE_ST_BLOCKS)
+	  fs_blocks = buf.st_blocks;
+#endif
+	}
+
+      initialized = true;
+    }
+}
+
+void
+file_stat::copy (const file_stat& fs)
+{
+  file_name = fs.file_name;
+  follow_links = fs.follow_links;
+  initialized = fs.initialized;
+  fail = fs.fail;
+  errmsg = fs.errmsg;
+  fs_mode = fs.fs_mode;
+  fs_ino = fs.fs_ino;
+  fs_dev = fs.fs_dev;
+  fs_nlink = fs.fs_nlink;
+  fs_uid = fs.fs_uid;
+  fs_gid = fs.fs_gid;
+  fs_size = fs.fs_size;
+  fs_atime = fs.fs_atime;
+  fs_mtime = fs.fs_mtime;
+  fs_ctime = fs.fs_ctime;
+
+#if defined (HAVE_ST_RDEV)
+  fs_rdev = fs.fs_rdev;
+#endif
+
+#if defined (HAVE_ST_BLKSIZE)
+  fs_blksize = fs.fs_blksize;
+#endif
+
+#if defined (HAVE_ST_BLOCKS)
+  fs_blocks = fs.fs_blocks;
+#endif
+}
+
+/*
+;;; Local Variables: ***
+;;; mode: C++ ***
+;;; End: ***
+*/
new file mode 100644
--- /dev/null
+++ b/liboctave/file-stat.h
@@ -0,0 +1,204 @@
+/*
+
+Copyright (C) 1996, 1997 John W. Eaton
+
+This file is part of Octave.
+
+Octave is free software; you can redistribute it and/or modify it
+under the terms of the GNU General Public License as published by the
+Free Software Foundation; either version 2, or (at your option) any
+later version.
+
+Octave is distributed in the hope that it will be useful, but WITHOUT
+ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+for more details.
+
+You should have received a copy of the GNU General Public License
+along with Octave; see the file COPYING.  If not, write to the Free
+Software Foundation, 59 Temple Place - Suite 330, Boston, MA  02111-1307, USA.
+
+*/
+
+#if !defined (octave_file_stat_h)
+#define octave_file_stat_h 1
+
+#include <string>
+
+#ifdef HAVE_SYS_TYPES_H
+#include <sys/types.h>
+#endif
+
+class
+file_stat
+{
+public:
+
+  file_stat (const string& n = string (), bool fl = true)
+    : file_name (n), follow_links (fl), initialized (false)
+      {
+	if (! file_name.empty ())
+	  update_internal ();
+      }
+
+  file_stat (const file_stat& f) { copy (f); }
+
+  file_stat& operator = (const file_stat& f)
+    {
+      if (this != &f)
+	copy (f);
+
+      return *this;
+    }
+
+  ~file_stat (void) { }
+
+  void get_stats (bool force = false)
+    {
+      if (! initialized || force)
+        update_internal (force);
+    }
+
+  void get_stats (const string& n, bool force = false)
+    {
+      if (n != file_name || ! initialized  || force)
+	{
+	  initialized = false;
+
+	  file_name = n;
+
+	  update_internal (force);
+	}
+    }
+
+  // File status and info.  These should only be called for objects
+  // that are already properly initialized.
+
+  bool is_blk (void) const;
+  bool is_chr (void) const;
+  bool is_dir (void) const;
+  bool is_fifo (void) const;
+  bool is_lnk (void) const;
+  bool is_reg (void) const;
+  bool is_sock (void) const;
+
+  ino_t ino (void) const { return fs_ino; }
+  dev_t dev (void) const { return fs_dev; }
+
+  nlink_t nlink (void) const { return fs_nlink; }
+
+  uid_t uid (void) const { return fs_uid; }
+  gid_t gid (void) const { return fs_gid; }
+
+  off_t size (void) const { return fs_size; }
+
+  time_t atime (void) const { return fs_atime; }
+  time_t mtime (void) const { return fs_mtime; }
+  time_t ctime (void) const { return fs_ctime; }
+
+#if defined (HAVE_ST_RDEV)
+  dev_t rdev (void) const { return fs_rdev; }
+#endif
+
+#if defined (HAVE_ST_BLKSIZE)
+  long blksize (void) const { return fs_blksize; }
+#endif
+
+#if defined (HAVE_ST_BLOCKS)
+  long blocks (void) const { return fs_blocks; }
+#endif
+
+  string mode_as_string (void) const;
+
+  bool ok (void) const { return initialized && ! fail; }
+
+  operator void* () const
+    { return ok ()
+	? static_cast<void *> (-1) : static_cast<void *> (0); }
+
+  bool exists (void) const { return ok (); }
+
+  string error (void) const { return ok () ? string () : errmsg; }
+
+  // Has the file referenced by this object been modified since TIME?
+  bool is_newer (time_t time) const { return fs_mtime > time; }
+
+  // It's nice to be able to hide the file_stat object if we don't
+  // really care about it.
+  static int is_newer (const string&, time_t);
+
+private:
+
+  // Name of the file.
+  string file_name;
+
+  // TRUE means follow symbolic links to the ultimate file (stat).
+  // FALSE means get information about the link itself (lstat).
+  bool follow_links;
+
+  // TRUE means we have already called stat.
+  bool initialized;
+
+  // TRUE means the stat for this file failed.
+  bool fail;
+
+  // If a failure occurs, this contains the system error text.
+  string errmsg;
+
+  // file type and permissions
+  mode_t fs_mode;
+
+  // serial number
+  ino_t fs_ino;
+
+  // device number
+  dev_t fs_dev;
+
+  // number of links
+  nlink_t fs_nlink;
+
+  // user ID of owner
+  uid_t fs_uid;
+
+  // group ID of owner
+  gid_t fs_gid;
+
+  // size in bytes, for regular files
+  off_t fs_size;
+
+  // time of last access
+  time_t fs_atime;
+
+  // time of last modification
+  time_t fs_mtime;
+
+  // time of last file status change
+  time_t fs_ctime;
+
+#if defined (HAVE_ST_RDEV)
+  // device number for special files
+  dev_t fs_rdev;
+#endif
+
+#if defined (HAVE_ST_BLKSIZE)
+  // best I/O block size
+  long fs_blksize;
+#endif
+
+#if defined (HAVE_ST_BLOCKS)
+  // number of 512-byte blocks allocated
+  long fs_blocks;
+#endif
+
+  void update_internal (bool force = false);
+
+  void copy (const file_stat&);
+};
+
+#endif
+
+/*
+;;; Local Variables: ***
+;;; mode: C++ ***
+;;; End: ***
+*/
--- a/liboctave/glob-match.cc
+++ b/liboctave/glob-match.cc
@@ -32,7 +32,7 @@
 #include <string>
 
 #include "file-stat.h"
-#include "oct-glob.h"
+#include "glob-match.h"
 #include "str-vec.h"
 
 bool
--- a/liboctave/glob-match.h
+++ b/liboctave/glob-match.h
@@ -20,8 +20,8 @@
 
 */
 
-#if !defined (octave_oct_glob_h)
-#define octave_oct_glob_h 1
+#if !defined (octave_glob_match_h)
+#define octave_glob_match_h 1
 
 #include <string>
 
new file mode 100644
--- /dev/null
+++ b/liboctave/lo-sysdep.cc
@@ -0,0 +1,120 @@
+/*
+
+Copyright (C) 1996, 1997 John W. Eaton
+
+This file is part of Octave.
+
+Octave is free software; you can redistribute it and/or modify it
+under the terms of the GNU General Public License as published by the
+Free Software Foundation; either version 2, or (at your option) any
+later version.
+
+Octave is distributed in the hope that it will be useful, but WITHOUT
+ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+for more details.
+
+You should have received a copy of the GNU General Public License
+along with Octave; see the file COPYING.  If not, write to the Free
+Software Foundation, 59 Temple Place - Suite 330, Boston, MA  02111-1307, USA.
+
+*/
+
+/*
+
+The function gethostname was adapted from a similar function from GNU
+Bash, the Bourne Again SHell, copyright (C) 1987, 1989, 1991 Free
+Software Foundation, Inc.
+
+*/
+
+#ifdef HAVE_CONFIG_H
+#include <config.h>
+#endif
+
+#include <string>
+
+#include <iostream.h>
+
+#ifdef HAVE_UNISTD_H
+#ifdef HAVE_SYS_TYPES_H
+#include <sys/types.h>
+#endif
+#include <unistd.h>
+#endif
+
+#if ! defined (HAVE_GETHOSTNAME) && defined (HAVE_SYS_UTSNAME_H)
+#include <sys/utsname.h>
+#endif
+
+#include "pathlen.h"
+
+string
+octave_getcwd (void)
+{
+  string retval;
+  char buf[MAXPATHLEN];
+
+#if defined (__EMX__)
+  char *tmp = _getcwd2 (buf, MAXPATHLEN);
+#else
+  char *tmp = getcwd (buf, MAXPATHLEN);
+#endif
+
+  if (tmp)
+    retval = tmp;
+
+  return retval;
+}
+
+int
+octave_chdir (const string& path)
+{
+#if defined (__EMX__)
+  int retval = -1;
+
+  char *tmp_path = strsave (path.c_str ());
+
+  if (path.length () == 2 && path[1] == ':')
+    {
+      char *upper_case_dir_name = strupr (tmp_path);
+      _chdrive (upper_case_dir_name[0]);
+      if (_getdrive () == upper_case_dir_name[0])
+	retval = _chdir2 ("/");
+    }
+  else
+    retval = _chdir2 (tmp_path);
+
+  delete [] tmp_path;
+
+  return retval;
+#else
+  return chdir (path.c_str ());
+#endif
+}
+
+#if ! defined (HAVE_GETHOSTNAME) && defined (HAVE_SYS_UTSNAME_H)
+
+int
+gethostname (char *name, int namelen)
+{
+  int i;
+  struct utsname ut;
+
+  --namelen;
+
+  uname (&ut);
+  i = strlen (ut.nodename) + 1;
+  strncpy (name, ut.nodename, i < namelen ? i : namelen);
+  name[namelen] = '\0';
+
+  return 0;
+}
+
+#endif
+
+/*
+;;; Local Variables: ***
+;;; mode: C++ ***
+;;; End: ***
+*/
new file mode 100644
--- /dev/null
+++ b/liboctave/lo-sysdep.h
@@ -0,0 +1,44 @@
+/*
+
+Copyright (C) 1996, 1997 John W. Eaton
+
+This file is part of Octave.
+
+Octave is free software; you can redistribute it and/or modify it
+under the terms of the GNU General Public License as published by the
+Free Software Foundation; either version 2, or (at your option) any
+later version.
+
+Octave is distributed in the hope that it will be useful, but WITHOUT
+ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+for more details.
+
+You should have received a copy of the GNU General Public License
+along with Octave; see the file COPYING.  If not, write to the Free
+Software Foundation, 59 Temple Place - Suite 330, Boston, MA  02111-1307, USA.
+
+*/
+
+#if !defined (octave_liboctave_sysdep_h)
+#define octave_liboctave_sysdep_h 1
+
+#include <string>
+
+#include "lo-ieee.h"
+
+extern string octave_getcwd (void);
+
+extern bool octave_chdir (const string&);
+
+#if ! defined (HAVE_GETHOSTNAME) && defined (HAVE_SYS_UTSNAME_H)
+extern int gethostname (char *, int);
+#endif
+
+#endif
+
+/*
+;;; Local Variables: ***
+;;; mode: C++ ***
+;;; End: ***
+*/
--- a/liboctave/lo-utils.cc
+++ b/liboctave/lo-utils.cc
@@ -26,7 +26,19 @@
 #endif
 
 #include <climits>
+#include <cstdlib>
+#include <cstdio>
 
+#include <string>
+
+#ifdef HAVE_UNISTD_H
+#ifdef HAVE_SYS_TYPES_H
+#include <sys/types.h>
+#endif
+#include <unistd.h>
+#endif
+
+#include "lo-error.h"
 #include "lo-mappers.h"
 #include "lo-utils.h"
 
@@ -53,6 +65,103 @@
     return floor (x + 0.5);
 }
 
+// Save a string.
+
+char *
+strsave (const char *s)
+{
+  if (! s)
+    return 0;
+
+  int len = strlen (s);
+  char *tmp = new char [len+1];
+  tmp = strcpy (tmp, s);
+  return tmp;
+}
+
+// This function was adapted from xputenv from Karl Berry's kpathsearch
+// library.
+
+// XXX FIXME XXX -- make this do the right thing if we don't have a
+// SMART_PUTENV.
+
+void
+octave_putenv (const string& name, const string& value)
+{
+  int new_len = name.length () + value.length () + 2;
+
+  char *new_item = static_cast<char*> (malloc (new_len));
+
+  sprintf (new_item, "%s=%s", name.c_str (), value.c_str ());
+
+  // As far as I can see there's no way to distinguish between the
+  // various errors; putenv doesn't have errno values.
+
+  if (putenv (new_item) < 0)
+    (*current_liboctave_error_handler) ("putenv (%s) failed", new_item);
+}
+
+string
+octave_fgets (FILE *f)
+{
+  string retval;
+
+  int grow_size = 1024;
+  int max_size = grow_size;
+
+  char *buf = static_cast<char *> (malloc (max_size));
+  char *bufptr = buf;
+  int len = 0;
+
+  do
+    {
+      if (fgets (bufptr, grow_size, f))
+	{
+	  len = strlen (bufptr);
+
+	  if (len == grow_size - 1)
+	    {
+	      int tmp = bufptr - buf + grow_size - 1;
+	      grow_size *= 2;
+	      max_size += grow_size;
+	      buf = static_cast<char *> (realloc (buf, max_size));
+	      bufptr = buf + tmp;
+
+	      if (*(bufptr-1) == '\n')
+		{
+		  *bufptr = '\0';
+		  retval = buf;
+		}
+	    }
+	  else if (bufptr[len-1] != '\n')
+	    {
+	      bufptr[len++] = '\n';
+	      bufptr[len] = '\0';
+	      retval = buf;
+	    }
+	  else
+	    retval = buf;
+	}
+      else
+	{
+	  if (len == 0)
+	    {
+	      free (buf);
+
+	      buf = 0;
+	    }
+
+	  break;
+	}
+    }
+  while (retval.empty ());
+
+  if (buf)
+    free (buf);
+
+  return retval;
+}
+
 /*
 ;;; Local Variables: ***
 ;;; mode: C++ ***
--- a/liboctave/lo-utils.h
+++ b/liboctave/lo-utils.h
@@ -23,9 +23,19 @@
 #if !defined (octave_liboctave_utils_h)
 #define octave_liboctave_utils_h 1
 
+#include <cstdio>
+
+#include <string>
+
 extern int NINT (double x);
 extern double D_NINT (double x);
 
+extern char *strsave (const char *);
+
+extern void octave_putenv (const string&, const string&);
+
+extern string octave_fgets (FILE *);
+
 #endif
 
 /*
--- a/liboctave/mach-info.cc
+++ b/liboctave/mach-info.cc
@@ -70,7 +70,7 @@
 }
 
 void
-oct_mach_info::init_float_format (void)
+oct_mach_info::init_float_format (void) const
 {
   float_params fp[5];
 
@@ -124,7 +124,7 @@
 }
 
 void
-oct_mach_info::ten_little_endians (void)
+oct_mach_info::ten_little_endians (void) const
 {
   // Are we little or big endian?  From Harbison & Steele.
 
@@ -145,31 +145,44 @@
   ten_little_endians ();
 }
 
+bool
+oct_mach_info::instance_ok (void)
+{
+  bool retval = true;
+
+  if (! instance)
+    instance = new oct_mach_info ();
+
+  if (! instance)
+    {
+      (*current_liboctave_error_handler)
+	("unable to create command history object!");
+
+      retval = false;
+    }
+
+  return retval;
+}
+
 oct_mach_info::float_format
 oct_mach_info::native_float_format (void)
 {
-  if (! instance)
-    instance = new oct_mach_info ();
-
-  return instance->native_float_fmt;
+  return (instance_ok ())
+    ? instance->native_float_fmt : oct_mach_info::unknown;
 }
 
 bool
 oct_mach_info::words_big_endian (void)
 {
-  if (! instance)
-    instance = new oct_mach_info ();
-
-  return instance->big_chief;
+  return (instance_ok ())
+    ? instance->big_chief : false;
 }
 
 bool
 oct_mach_info::words_little_endian (void)
 {
-  if (! instance)
-    instance = new oct_mach_info ();
-
-  return ! instance->big_chief;
+  return (instance_ok ())
+    ? (! instance->big_chief) : false;
 }
 
 oct_mach_info::float_format
--- a/liboctave/mach-info.h
+++ b/liboctave/mach-info.h
@@ -28,6 +28,10 @@
 class
 oct_mach_info
 {
+protected:
+
+  oct_mach_info (void);
+
 public:
 
   enum float_format
@@ -41,7 +45,7 @@
       cray
     };
 
-  oct_mach_info (void);
+  static bool instance_ok (void);
 
   static float_format native_float_format (void);
 
@@ -57,15 +61,15 @@
 
   static oct_mach_info *instance;
 
-  void init_float_format (void);
+  void init_float_format (void) const;
 
-  void ten_little_endians (void);
+  void ten_little_endians (void) const;
 
   // The floating point format for the current machine.
-  float_format native_float_fmt;
+  mutable float_format native_float_fmt;
 
   // TRUE if the byte order on this system is big endian.
-  bool big_chief;
+  mutable bool big_chief;
 
   // No copying!
 
new file mode 100644
--- /dev/null
+++ b/liboctave/oct-env.cc
@@ -0,0 +1,493 @@
+/*
+
+Copyright (C) 1996, 1997 John W. Eaton
+
+This file is part of Octave.
+
+Octave is free software; you can redistribute it and/or modify it
+under the terms of the GNU General Public License as published by the
+Free Software Foundation; either version 2, or (at your option) any
+later version.
+
+Octave is distributed in the hope that it will be useful, but WITHOUT
+ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+for more details.
+
+You should have received a copy of the GNU General Public License
+along with Octave; see the file COPYING.  If not, write to the Free
+Software Foundation, 59 Temple Place - Suite 330, Boston, MA  02111-1307, USA.
+
+*/
+
+/*
+
+The functions listed below were adapted from a similar functions
+from GNU Bash, the Bourne Again SHell, copyright (C) 1987, 1989, 1991
+Free Software Foundation, Inc.
+
+  octave_env::do_absolute_pathname
+  octave_env::do_base_pathname
+  octave_env::do_chdir
+  octave_env::do_getcwd
+  octave_env::do_make_absolute
+  octave_env::do_polite_directory_format
+  octave_env::pathname_backup
+
+*/ 
+
+#ifdef HAVE_CONFIG_H
+#include <config.h>
+#endif
+
+#include <cerrno>
+#include <cstdlib>
+
+#ifdef HAVE_UNISTD_H
+#ifdef HAVE_SYS_TYPES_H
+#include <sys/types.h>
+#endif
+#include <unistd.h>
+#endif
+
+#ifdef HAVE_PWD_H
+#include <pwd.h>
+#endif
+
+#include "lo-error.h"
+#include "lo-sysdep.h"
+#include "lo-utils.h"
+#include "oct-env.h"
+
+octave_env::octave_env (void)
+  : follow_symbolic_links (true), verbatim_pwd (true),
+    current_directory (), program_name (), program_invocation_name (),
+    user_name (), host_name ()
+{
+  // Get a real value for the current directory.
+  do_getcwd ();
+
+  // Etc.
+  do_get_user_name ();
+
+  do_get_host_name ();
+}
+
+octave_env *octave_env::instance = 0;
+
+bool
+octave_env::instance_ok (void)
+{
+  bool retval = true;
+
+  if (! instance)
+    instance = new octave_env ();
+
+  if (! instance)
+    {
+      (*current_liboctave_error_handler)
+	("unable to create current working directoy object!");
+
+      retval = false;
+    }
+
+  return retval;
+}
+
+string
+octave_env::polite_directory_format (const string& name)
+{
+  return (instance_ok ())
+    ? instance->do_polite_directory_format (name) : string ();
+}
+
+bool
+octave_env::absolute_pathname (const string& s)
+{
+  return (instance_ok ())
+    ? instance->do_absolute_pathname (s) : false;
+}
+
+string
+octave_env::base_pathname (const string& s)
+{
+  return (instance_ok ())
+    ? instance->do_base_pathname (s) : string ();
+}
+
+string
+octave_env::make_absolute (const string& s, const string& dot_path)
+{
+  return (instance_ok ())
+    ? instance->do_make_absolute (s, dot_path) : string ();
+}
+
+string
+octave_env::getcwd ()
+{
+  return (instance_ok ())
+    ? instance->do_getcwd () : string ();
+}
+
+string
+octave_env::get_home_directory ()
+{
+  return (instance_ok ())
+    ? instance->do_get_home_directory () : string ();
+}
+
+string
+octave_env::get_program_name (void)
+{
+  return (instance_ok ())
+    ? instance->program_name : string ();
+}
+
+string
+octave_env::get_program_invocation_name (void)
+{
+  return (instance_ok ())
+    ? instance->program_invocation_name : string ();
+}
+
+void
+octave_env::set_program_name (const string& s)
+{
+  if (instance_ok ())
+    instance->do_set_program_name (s);
+}
+
+string
+octave_env::get_user_name (void)
+{
+  return (instance_ok ())
+    ? instance->do_get_user_name () : string ();
+}
+
+string
+octave_env::get_host_name (void)
+{
+  return (instance_ok ())
+    ? instance->do_get_host_name () : string ();
+}
+
+// XXX FIXME XXX -- this leaves no way to distinguish between a
+// variable that is not set and one that is set to the empty string.
+// Is this a problem?
+
+string
+octave_env::getenv (const string& name)
+{
+  return (instance_ok ())
+    ? instance->do_getenv (name) : string ();
+}
+
+void
+octave_env::putenv (const string& name, const string& value)
+{
+  octave_putenv (name, value);
+}
+
+bool
+octave_env::chdir (const string& newdir)
+{
+  return (instance_ok ())
+    ? instance->do_chdir (newdir) : false;
+}
+
+void
+octave_env::do_set_program_name (const string& s) const
+{
+  program_invocation_name = s;
+
+  size_t pos = program_invocation_name.rfind ('/');
+
+  program_name = (pos == NPOS)
+    ? program_invocation_name : program_invocation_name.substr (pos+1);
+}
+
+// Return a pretty pathname.  If the first part of the pathname is the
+// same as $HOME, then replace that with `~'.
+
+string
+octave_env::do_polite_directory_format (const string& name) const
+{
+  string retval;
+
+  string home_dir = do_get_home_directory ();
+
+  size_t len = home_dir.length ();
+
+  if (len > 1 && home_dir.compare (name, 0, len) == 0
+      && (name.length () == len || name[len] == '/'))
+    {
+      retval = "~";
+      retval.append (name.substr (len));
+    }
+  else
+    retval = name;
+
+  return retval;
+}
+
+// Return 1 if STRING contains an absolute pathname, else 0.
+
+bool
+octave_env::do_absolute_pathname (const string& s) const
+{
+  if (s.empty ())
+    return 0;
+
+  if (s[0] == '/')
+    return true;
+
+  if (s[0] == '.')
+    {
+      if (s[1] == '\0' || s[1] == '/')
+	return true;
+
+      if (s[1] == '.')
+	if (s[2] == '\0' || s[2] == '/')
+	  return true;
+    }
+
+  return false;
+}
+
+// Return the `basename' of the pathname in STRING (the stuff after
+// the last '/').  If STRING is not a full pathname, simply return it.
+
+string
+octave_env::do_base_pathname (const string& s) const
+{
+  if (! do_absolute_pathname (s))
+    return s;
+
+  size_t pos = s.rfind ('/');
+
+  if (pos == NPOS)
+    return s;
+  else
+    return s.substr (pos+1);
+}
+
+// Turn STRING (a pathname) into an absolute pathname, assuming that
+// DOT_PATH contains the symbolic location of '.'.
+
+string
+octave_env::do_make_absolute (const string& s, const string& dot_path) const
+{
+#if defined (__EMX__)
+  if (s.length () > 1 && s[1] == ':')
+    return s;
+#endif
+
+  if (dot_path.empty () || s[0] == '/' || s.empty ())
+    return s;
+
+  string current_path = dot_path;
+
+  if (current_path.empty ())
+    current_path = "./";
+
+  size_t pos = current_path.length () - 1;
+
+  if (current_path[pos] != '/')
+    current_path.append ("/");
+
+  size_t i = 0;
+  size_t slen = s.length ();
+
+  while (i < slen)
+    {
+      if (s[i] == '.')
+	{
+	  if (i + 1 == slen)
+	    return current_path;
+
+	  if (s[i+1] == '/')
+	    {
+	      i += 2;
+	      continue;
+	    }
+
+	  if (s[i+1] == '.' && (i + 2 == slen || s[i+2] == '/'))
+	    {
+	      i += 2;
+
+	      if (i != slen)
+		i++;
+
+	      pathname_backup (current_path, 1);
+
+	      continue;
+	    }
+	}
+
+      size_t tmp = s.find ('/', i);
+
+      if (tmp == NPOS)
+	{
+	  current_path.append (s, i, tmp-i);
+	  break;
+	}
+      else
+	{
+	  current_path.append (s, i, tmp-i+1);
+	  i = tmp + 1;
+	}
+    }
+
+  return current_path;
+}
+
+// Return a consed string which is the current working directory.
+
+string
+octave_env::do_getcwd ()
+{
+  if (! follow_symbolic_links)
+    current_directory = "";
+
+  if (verbatim_pwd || current_directory.empty ())
+    current_directory = ::octave_getcwd ();
+
+  return current_directory;
+}
+
+// This value is not cached because it can change while Octave is
+// running.
+
+string
+octave_env::do_get_home_directory (void) const
+{
+  string hd = do_getenv ("HOME");
+
+  return hd.empty () ? string ("I have no home!") : hd;
+}
+
+string
+octave_env::do_get_user_name (void) const
+{
+  // XXX FIXME XXX -- is it possible for this to change while Octave
+  // is running?
+
+  if (user_name.empty ())
+    {
+      struct passwd *entry = getpwuid (getuid ());
+
+      user_name = entry ? entry->pw_name : "I have no name!";
+    }
+
+  return user_name;
+}
+
+string
+octave_env::do_get_host_name (void) const
+{
+  // XXX FIXME XXX -- is it possible for this to change while Octave
+  // is running?
+
+  if (host_name.empty ())
+    {
+      char hostname[256];
+
+      int status = gethostname (hostname, 255);
+
+      host_name = (status < 0) ? "I have no host!" : hostname;
+    }
+
+  return host_name;
+}
+
+string
+octave_env::do_getenv (const string& name) const
+{
+  char *value = ::getenv (name.c_str ());
+
+  return value ? value : "";
+}
+
+// Do the work of changing to the directory NEWDIR.  Handle symbolic
+// link following, etc.
+
+bool
+octave_env::do_chdir (const string& newdir)
+{
+  bool retval = false;
+
+  string tmp;
+
+  if (follow_symbolic_links)
+    {
+      if (current_directory.empty ())
+	do_getcwd ();
+
+      if (current_directory.empty ())
+	tmp = newdir;
+      else
+	tmp = do_make_absolute (newdir, current_directory);
+
+      // Get rid of trailing `/'.
+
+      size_t len = tmp.length ();
+
+      if (len > 1)
+	{
+	  if (tmp[--len] == '/')
+	    tmp.resize (len);
+	}
+
+      if (! ::octave_chdir (tmp))
+	{
+	  current_directory = tmp;
+	  retval = true;
+	}
+    }
+  else
+    retval = (! ::octave_chdir (newdir));
+
+  return retval;
+}
+
+// Remove the last N directories from PATH.
+
+void
+octave_env::pathname_backup (string& path, int n) const
+{
+  if (path.empty ())
+    return;
+
+  size_t i = path.length () - 1;
+
+  while (n--)
+    {
+      while (path[i] == '/' && i > 0)
+	i--;
+
+      while (path[i] != '/' && i > 0)
+	i--;
+
+      i++;
+    }
+
+  path.resize (i);
+}
+
+void
+octave_env::error (int err_num) const
+{
+  (*current_liboctave_error_handler) ("%s", strerror (err_num));
+}
+
+void
+octave_env::error (const string& s) const
+{
+  (*current_liboctave_error_handler) ("%s", s.c_str ());
+}
+
+/*
+;;; Local Variables: ***
+;;; mode: C++ ***
+;;; End: ***
+*/
new file mode 100644
--- /dev/null
+++ b/liboctave/oct-env.h
@@ -0,0 +1,135 @@
+/*
+
+Copyright (C) 1996, 1997 John W. Eaton
+
+This file is part of Octave.
+
+Octave is free software; you can redistribute it and/or modify it
+under the terms of the GNU General Public License as published by the
+Free Software Foundation; either version 2, or (at your option) any
+later version.
+
+Octave is distributed in the hope that it will be useful, but WITHOUT
+ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+for more details.
+
+You should have received a copy of the GNU General Public License
+along with Octave; see the file COPYING.  If not, write to the Free
+Software Foundation, 59 Temple Place - Suite 330, Boston, MA  02111-1307, USA.
+
+*/
+
+#if !defined (octave_env_h)
+#define octave_env_h 1
+
+#include <string>
+
+class
+octave_env
+{
+protected:
+
+  octave_env (void);
+
+public:
+
+  static string polite_directory_format (const string& name);
+
+  static bool absolute_pathname (const string& s);
+
+  static string base_pathname (const string& s);
+
+  static string make_absolute (const string& s, const string& dot_path);
+
+  static string getcwd (void);
+
+  static string get_home_directory (void);
+
+  static string get_program_name (void);
+
+  static string get_program_invocation_name (void);
+
+  static string get_user_name (void);
+
+  static string get_host_name (void);
+
+  static string getenv (const string& name);
+
+  static void putenv (const string& name, const string& value);
+
+  static bool chdir (const string& newdir);
+
+  static void set_program_name (const string& s);
+
+private:
+
+  static bool instance_ok (void);
+
+  string do_polite_directory_format (const string& name) const;
+
+  bool do_absolute_pathname (const string& s) const;
+
+  string do_base_pathname (const string& s) const;
+
+  string do_make_absolute (const string& s, const string& dot_path) const;
+
+  string do_getcwd (void);
+
+  string do_get_home_directory (void) const;
+
+  string do_get_user_name (void) const;
+
+  string do_get_host_name (void) const;
+
+  string do_getenv (const string& name) const;
+
+  void do_putenv (const string& name, const string& value) const;
+
+  bool do_chdir (const string& newdir);
+
+  void do_set_program_name (const string& s) const;
+
+  void pathname_backup (string& path, int n) const;
+
+  void error (int) const;
+
+  void error (const string&) const;
+
+  // No copying!
+
+  octave_env (const octave_env&);
+
+  octave_env& operator = (const octave_env&);
+
+  // The real thing.
+  static octave_env *instance;
+
+  // TRUE means follow symbolic links that point to directories just
+  // as if they are real directories.
+  bool follow_symbolic_links;
+
+  // TRUE means that pwd always give verbatim directory, regardless
+  // of symbolic link following.
+  bool verbatim_pwd;
+
+  // Where are we?
+  string current_directory;
+
+  // Etc.
+  mutable string program_name;
+
+  mutable string program_invocation_name;
+
+  mutable string user_name;
+
+  mutable string host_name;
+};
+
+#endif
+
+/*
+;;; Local Variables: ***
+;;; mode: C++ ***
+;;; End: ***
+*/
--- a/liboctave/statdefs.h
+++ b/liboctave/statdefs.h
@@ -26,7 +26,10 @@
 #ifdef HAVE_SYS_TYPES_H
 #include <sys/types.h>
 #endif
+
+#ifdef HAVE_SYS_STAT_H
 #include <sys/stat.h>
+#endif
 
 #ifndef S_ISREG			/* Doesn't have POSIX.1 stat stuff. */
 #define mode_t unsigned short
--- a/liboctave/str-vec.cc
+++ b/liboctave/str-vec.cc
@@ -28,7 +28,7 @@
 
 #include <iostream.h>
 
-#include "oct-term.h"
+#include "cmd-edit.h"
 #include "str-vec.h"
 
 // Create a string vector from a NULL terminated list of C strings.
@@ -80,7 +80,7 @@
 
   // Calculate the maximum number of columns that will fit.
 
-  int line_length = terminal_columns ();
+  int line_length = command_editor::terminal_cols ();
   int cols = line_length / max_name_length;
   if (cols == 0)
     cols = 1;
--- a/src/Makefile.in
+++ b/src/Makefile.in
@@ -162,7 +162,7 @@
 	-L../kpathsea -L../glob -L../dlfcn -L. $(RLD_FLAG)
 
 OCTAVE_LIBS = -loctinterp -loctave -ltinst -lcruft \
-	$(LIBPLPLOT) -lreadline -lkpathsea -lglob $(LIBDLFCN)
+	$(LIBPLPLOT) $(LIBREADLINE) -lkpathsea -lglob $(LIBDLFCN)
 
 LIBS_TO_INSTALL = liboctinterp.a libtinst.a
 
@@ -343,7 +343,7 @@
 
 clean:
 	rm -f *.a *.o *.d *.df *.oct pic/*.o
-	rm -f builtins.cc defaults.h oct-conf.h def-files var-files
+	rm -f builtins.cc ops.cc defaults.h oct-conf.h def-files var-files
 	if $(SHARED_LIBS); then rm -f *.$(SHLEXT); fi
 .PHONY: clean
 
--- a/src/defaults.cc
+++ b/src/defaults.cc
@@ -45,6 +45,8 @@
 #include <unistd.h>
 #endif
 
+#include "oct-env.h"
+
 #include <defaults.h>
 #include "defun.h"
 #include "error.h"
@@ -106,9 +108,9 @@
 static void
 set_octave_home (void)
 {
-  char *oh = getenv ("OCTAVE_HOME");
+  string oh = octave_env::getenv ("OCTAVE_HOME");
 
-  Voctave_home = oh ? string (oh) : string (OCTAVE_PREFIX);
+  Voctave_home = oh.empty () ? string (OCTAVE_PREFIX) : oh;
 }
 
 static void
@@ -150,20 +152,20 @@
 static void
 set_default_exec_path (void)
 {
-  char *octave_exec_path = getenv ("OCTAVE_EXEC_PATH");
+  string octave_exec_path = octave_env::getenv ("OCTAVE_EXEC_PATH");
 
-  if (octave_exec_path)
-    Vexec_path = string (octave_exec_path);
-  else
+  if (octave_exec_path.empty ())
     {
-      char *shell_path = getenv ("PATH");
+      string shell_path = octave_env::getenv ("PATH");
 
-      if (shell_path)
+      if (! shell_path.empty ())
 	{
 	  Vexec_path = string (":");
 	  Vexec_path.append (shell_path);
 	}
     }
+  else
+    Vexec_path = string (octave_exec_path);
 }
 
 // Handle OCTAVE_PATH from the environment like TeX handles TEXINPUTS.
@@ -176,9 +178,9 @@
 {
   string std_path = subst_octave_home (OCTAVE_FCNFILEPATH);
 
-  char *oct_path = getenv ("OCTAVE_PATH");
+  string oct_path = octave_env::getenv ("OCTAVE_PATH");
 
-  Vload_path = oct_path ? string (oct_path) : std_path;
+  Vload_path = oct_path.empty () ? std_path : oct_path;
 }
 
 static void
@@ -186,23 +188,23 @@
 {
   string std_info_file = subst_octave_home (OCTAVE_INFOFILE);
 
-  char *oct_info_file = getenv ("OCTAVE_INFO_FILE");
+  string oct_info_file = octave_env::getenv ("OCTAVE_INFO_FILE");
 
-  Vinfo_file = oct_info_file ? string (oct_info_file) : std_info_file;
+  Vinfo_file = oct_info_file.empty () ? std_info_file : oct_info_file;
 }
 
 static void
 set_default_info_prog (void)
 {
-  char *oct_info_prog = getenv ("OCTAVE_INFO_PROGRAM");
+  string oct_info_prog = octave_env::getenv ("OCTAVE_INFO_PROGRAM");
 
-  if (oct_info_prog)
-    Vinfo_prog = string (oct_info_prog);
-  else
+  if (oct_info_prog.empty ())
     {
       Vinfo_prog = Varch_lib_dir;
       Vinfo_prog.append ("/info");
     }
+  else
+    Vinfo_prog = string (oct_info_prog);
 }
 
 static void
@@ -210,10 +212,10 @@
 {
   Veditor = "vi";
 
-  char *env_editor = getenv ("EDITOR");
+  string env_editor = octave_env::getenv ("EDITOR");
 
-  if (env_editor && *env_editor)
-    Veditor = string (env_editor);
+  if (! env_editor.empty ())
+    Veditor = env_editor;
 }
 
 static void
@@ -326,59 +328,34 @@
       std_path.append (SEPCHAR_STR);
       std_path.append (Varch_lib_dir);
 
-      int std_len = std_path.length ();
-
-      static char *putenv_cmd = 0;
-
-      delete [] putenv_cmd;
-
-      putenv_cmd = 0;
+      string path;
 
       int eplen = Vexec_path.length ();
 
       if (eplen > 0)
 	{
-	  int prepend = (Vexec_path[0] == ':');
-	  int append = (eplen > 1 && Vexec_path[eplen-1] == ':');
+	  bool prepend = (Vexec_path[0] == ':');
+	  bool append = (eplen > 1 && Vexec_path[eplen-1] == ':');
 
 	  if (prepend)
 	    {
+	      path = std_path + Vexec_path;
+
 	      if (append)
-		{
-		  putenv_cmd = new char [2 * std_len + eplen + 6];
-		  sprintf (putenv_cmd, "PATH=%s%s%s",
-			   std_path.c_str (), Vexec_path.c_str (),
-			   std_path.c_str ());
-		}
-	      else
-		{
-		  putenv_cmd = new char [std_len + eplen + 6];
-		  sprintf (putenv_cmd, "PATH=%s%s",
-			   std_path.c_str (), Vexec_path.c_str ());
-		}
+		path.append (std_path);
 	    }
 	  else
 	    {
+	      path = Vexec_path;
+
 	      if (append)
-		{
-		  putenv_cmd = new char [std_len + eplen + 6];
-		  sprintf (putenv_cmd, "PATH=%s%s",
-			   Vexec_path.c_str (), std_path.c_str ());
-		}
-	      else
-		{
-		  putenv_cmd = new char [eplen + 6];
-		  sprintf (putenv_cmd, "PATH=%s", Vexec_path.c_str ());
-		}
+		path.append (std_path);
 	    }
 	}
       else
-	{
-	  putenv_cmd = new char [std_len+6];
-	  sprintf (putenv_cmd, "PATH=%s", std_path.c_str ());
-	}
+	path = std_path;
 
-      putenv (putenv_cmd);
+      octave_env::putenv ("PATH", path);
     }
 
   return status;
--- a/src/dirfns.cc
+++ b/src/dirfns.cc
@@ -20,19 +20,6 @@
 
 */
 
-/*
-
-The functions listed below were adapted from a similar functions
-from GNU Bash, the Bourne Again SHell, copyright (C) 1987, 1989, 1991
-Free Software Foundation, Inc.
-
-  polite_directory_format  absolute_pathname
-  base_pathname
-  make_absolute            pathname_backup
-  change_to_directory      get_working_directory
-
-*/ 
-
 #ifdef HAVE_CONFIG_H
 #include <config.h>
 #endif
@@ -54,19 +41,20 @@
 #include <unistd.h>
 #endif
 
-#include "oct-glob.h"
+#include "file-ops.h"
+#include "file-stat.h"
+#include "glob-match.h"
+#include "oct-env.h"
 #include "str-vec.h"
 
 #include "defun.h"
 #include "dir-ops.h"
 #include "dirfns.h"
 #include "error.h"
-#include "file-ops.h"
 #include "gripes.h"
 #include "help.h"
 #include "oct-obj.h"
 #include "pager.h"
-#include "pathlen.h"
 #include "procstream.h"
 #include "pt-plot.h"
 #include "sysdep.h"
@@ -75,239 +63,14 @@
 #include "utils.h"
 #include "variables.h"
 
-// The current working directory.
-string Vcurrent_directory;
-
-// Non-zero means follow symbolic links that point to directories just
-// as if they are real directories.
-static int follow_symbolic_links = 1;
-
-// Non-zero means that pwd always give verbatim directory, regardless
-// of symbolic link following.
-static int verbatim_pwd = 1;
-
-// Remove the last N directories from PATH.  Do not PATH blank.
-// PATH must contain enough space for MAXPATHLEN characters.
-
-static void
-pathname_backup (string& path, int n)
-{
-  if (path.empty ())
-    return;
-
-  size_t i = path.length () - 1;
-
-  while (n--)
-    {
-      while (path[i] == '/' && i > 0)
-	i--;
-
-      while (path[i] != '/' && i > 0)
-	i--;
-
-      i++;
-    }
-
-  path.resize (i);
-}
-
-// Return a pretty pathname.  If the first part of the pathname is the
-// same as $HOME, then replace that with `~'.
-
-string
-polite_directory_format (const string& name)
-{
-  string retval;
-
-  size_t len = Vhome_directory.length ();
-
-  if (len > 1 && Vhome_directory.compare (name, 0, len) == 0
-      && (name.length () == len || name[len] == '/'))
-    {
-      retval = "~";
-      retval.append (name.substr (len));
-    }
-  else
-    retval = name;
-
-  return retval;
-}
-
-// Return 1 if STRING contains an absolute pathname, else 0.
-
-static int
-absolute_pathname (const string& s)
-{
-  if (s.empty ())
-    return 0;
-
-  if (s[0] == '/')
-    return 1;
-
-  if (s[0] == '.')
-    {
-      if (s[1] == '\0' || s[1] == '/')
-	return 1;
-
-      if (s[1] == '.')
-	if (s[2] == '\0' || s[2] == '/')
-	  return 1;
-    }
-
-  return 0;
-}
-
-// Return the `basename' of the pathname in STRING (the stuff after
-// the last '/').  If STRING is not a full pathname, simply return it.
-
-string
-base_pathname (const string& s)
-{
-  if (! absolute_pathname (s))
-    return s;
-
-  size_t pos = s.rfind ('/');
-
-  if (pos == NPOS)
-    return s;
-  else
-    return s.substr (pos+1);
-}
-
-// Turn STRING (a pathname) into an absolute pathname, assuming that
-// DOT_PATH contains the symbolic location of '.'.
-
-string
-make_absolute (const string& s, const string& dot_path)
-{
-#if defined (__EMX__)
-  if (s.length () > 1 && s[1] == ':')
-    return s;
-#endif
-
-  if (dot_path.empty () || s[0] == '/' || s.empty ())
-    return s;
-
-  string current_path = dot_path;
-
-  if (current_path.empty ())
-    current_path = "./";
-
-  size_t pos = current_path.length () - 1;
-
-  if (current_path[pos] != '/')
-    current_path.append ("/");
-
-  size_t i = 0;
-  size_t slen = s.length ();
-
-  while (i < slen)
-    {
-      if (s[i] == '.')
-	{
-	  if (i + 1 == slen)
-	    return current_path;
-
-	  if (s[i+1] == '/')
-	    {
-	      i += 2;
-	      continue;
-	    }
-
-	  if (s[i+1] == '.' && (i + 2 == slen || s[i+2] == '/'))
-	    {
-	      i += 2;
-
-	      if (i != slen)
-		i++;
-
-	      pathname_backup (current_path, 1);
-
-	      continue;
-	    }
-	}
-
-      size_t tmp = s.find ('/', i);
-
-      if (tmp == NPOS)
-	{
-	  current_path.append (s, i, tmp-i);
-	  break;
-	}
-      else
-	{
-	  current_path.append (s, i, tmp-i+1);
-	  i = tmp + 1;
-	}
-    }
-
-  return current_path;
-}
-
-// Return a consed string which is the current working directory.
-// FOR_WHOM is the name of the caller for error printing.
-
-string
-get_working_directory (const string& for_whom)
-{
-  if (! follow_symbolic_links)
-    Vcurrent_directory = "";
-
-  if (Vcurrent_directory.empty ())
-    {
-      Vcurrent_directory = octave_getcwd ();
-
-      if (Vcurrent_directory.empty ())
-	warning ("%s: can't find current directory!", for_whom.c_str ());
-    }
-
-  return Vcurrent_directory;
-}
-
-// Do the work of changing to the directory NEWDIR.  Handle symbolic
-// link following, etc.
-
-static int
-change_to_directory (const string& newdir)
-{
-  string tmp;
-
-  if (follow_symbolic_links)
-    {
-      if (Vcurrent_directory.empty ())
-	get_working_directory ("cd_links");
-
-      if (Vcurrent_directory.empty ())
-	tmp = newdir;
-      else
-	tmp = make_absolute (newdir, Vcurrent_directory);
-
-      // Get rid of trailing `/'.
-
-      size_t len = tmp.length ();
-
-      if (len > 1)
-	{
-	  if (tmp[--len] == '/')
-	    tmp.resize (len);
-	}
-
-      if (octave_chdir (tmp) < 0)
-	return 0;
-      else
-	{
-	  Vcurrent_directory = tmp;
-	  return 1;
-	}
-    }
-  else
-    return (octave_chdir (newdir) < 0) ? 0 : 1;
-}
+// XXX FIXME XXX -- changing the plotter directory should be handled
+// by registering a function for octave_env::chdir to call so that
+// this function can be eliminated.
 
 static int
 octave_change_to_directory (const string& newdir)
 {
-  int cd_ok = change_to_directory (newdir);
+  int cd_ok = octave_env::chdir (newdir);
 
   if (cd_ok)
     do_external_plotter_cd (newdir);
@@ -335,7 +98,7 @@
 
   if (argc > 1)
     {
-      string dirname = oct_tilde_expand (argv[1]);
+      string dirname = file_ops::tilde_expand (argv[1]);
 
       if (dirname.length () > 0
 	  && ! octave_change_to_directory (dirname))
@@ -345,16 +108,12 @@
     }
   else
     {
-      if (Vhome_directory.empty ()
-	  || ! octave_change_to_directory (Vhome_directory))
-	{
-	  return retval;
-	}
+      string home_dir = octave_env::get_home_directory ();
+
+      if (home_dir.empty () || ! octave_change_to_directory (home_dir))
+	return retval;
     }
 
-  string directory = get_working_directory ("cd");
-  bind_builtin_variable ("PWD", directory, 1);
-
   return retval;
 }
 
@@ -386,7 +145,7 @@
 
   ls_buf << "ls -C ";
   for (int i = 1; i < argc; i++)
-    ls_buf << oct_tilde_expand (argv[i]) << " ";
+    ls_buf << file_ops::tilde_expand (argv[i]) << " ";
 
   ls_buf << ends;
   char *ls_command = ls_buf.str ();
@@ -417,19 +176,12 @@
   "pwd (): print current working directory")
 {
   octave_value_list retval;
-  string directory;
 
-  if (verbatim_pwd)
-    {
-      directory = octave_getcwd ();
+  string directory = octave_env::getcwd ();
 
-      if (directory.empty ())
-	warning ("pwd: can't find working directory!");
-    }
+  if (directory.empty ())
+    warning ("pwd: can't find working directory!");
   else
-    directory = get_working_directory ("pwd");
-
-  if (! directory.empty ())
     {
       if (nargout == 0)
 	octave_stdout << directory << "\n";
@@ -463,7 +215,7 @@
 	gripe_wrong_type_arg ("readdir", args(0));
       else
 	{
-	  dir_entry dir (oct_tilde_expand (dirname));
+	  dir_entry dir (file_ops::tilde_expand (dirname));
 
 	  if (dir)
 	    {
@@ -509,8 +261,8 @@
 	{
 	  string msg;
 
-	  int status = oct_mkdir (oct_tilde_expand (dirname),
-				  0777, msg);
+	  int status = file_ops::mkdir (file_ops::tilde_expand (dirname),
+					0777, msg);
 
 	  retval(0) = static_cast<double> (status);
 
@@ -547,7 +299,7 @@
 	{
 	  string msg;
 
-	  int status = oct_rmdir (oct_tilde_expand (dirname), msg);
+	  int status = file_ops::rmdir (file_ops::tilde_expand (dirname), msg);
 
 	  retval(0) = static_cast<double> (status);
 
@@ -590,7 +342,7 @@
 	    {
 	      string msg;
 
-	      int status = oct_rename (from, to, msg);
+	      int status = file_ops::rename (from, to, msg);
 
 	      retval(0) = static_cast<double> (status);
 
@@ -623,7 +375,7 @@
 	gripe_wrong_type_arg ("glob", args(0));
       else
 	{
-	  glob_match pattern (oct_tilde_expand (pat));
+	  glob_match pattern (file_ops::tilde_expand (pat));
 
 	  string_vector list = pattern.glob ();
 
@@ -657,7 +409,7 @@
 	gripe_wrong_type_arg ("fnmatch", args(0));
       else
 	{
-	  glob_match pattern (oct_tilde_expand (pat));
+	  glob_match pattern (file_ops::tilde_expand (pat));
 
 	  Array<bool> tmp = pattern.match (str);
 
@@ -677,31 +429,6 @@
   return retval;
 }
 
-static int
-pwd (void)
-{
-  int status = 0;
-
-  string s = builtin_string_variable ("PWD");
-
-  if (s.empty ())
-    {
-      gripe_invalid_value_specified ("PWD");
-      status = -1;
-    }
-  else
-    Vcurrent_directory = s;
-
-  return status;
-}
-
-void
-symbols_of_dirfns (void)
-{
-  DEFCONST (PWD, get_working_directory ("initialize_globals"), 0, pwd,
-    "current working directory");
-}
-
 /*
 ;;; Local Variables: ***
 ;;; mode: C++ ***
--- a/src/dynamic-ld.cc
+++ b/src/dynamic-ld.cc
@@ -181,33 +181,43 @@
 
 #endif
 
-static octave_dynamic_loader *
-make_dynamic_loader (void)
+octave_dynamic_loader *octave_dynamic_loader::instance = 0;
+
+bool
+octave_dynamic_loader::instance_ok (void)
+{
+  bool retval = true;
+
+  if (! instance)
+    make_dynamic_loader ();
+
+  if (! instance)
+    {
+      error ("unable to create command history object!");
+
+      retval = false;
+    }
+
+  return retval;
+}
+
+void
+octave_dynamic_loader::make_dynamic_loader (void)
 {
 #if defined (WITH_DL)
-  return new octave_dlopen_dynamic_loader ();
+  instance = new octave_dlopen_dynamic_loader ();
 #elif defined (WITH_SHL)
-  return new octave_sh_load_dynamic_loader ();
+  instance = new octave_sh_load_dynamic_loader ();
 #else
-  return new octave_dynamic_loader ();
+  instance = new octave_dynamic_loader ();
 #endif
 }
 
-octave_dynamic_loader *octave_dynamic_loader::instance = 0;
-
-octave_dynamic_loader::octave_dynamic_loader (void)
-{
-}
-
-octave_dynamic_loader::~octave_dynamic_loader (void)
-{
-}
-
 int
 octave_dynamic_loader::load_fcn_from_dot_oct_file (const string& fcn_name)
 {
-  if (! instance)
-    instance = make_dynamic_loader ();
+  if (! instance_ok ())
+    make_dynamic_loader ();
 
   int retval = 0;
 
--- a/src/dynamic-ld.h
+++ b/src/dynamic-ld.h
@@ -32,30 +32,36 @@
 {
 protected:
 
-  octave_dynamic_loader (void);
+  octave_dynamic_loader (void) { }
 
 public:
 
   typedef octave_builtin * (*builtin_fcn) (void);
 
-  virtual ~octave_dynamic_loader (void);
+  virtual ~octave_dynamic_loader (void) { }
 
   static int load_fcn_from_dot_oct_file (const string& fcn_name);
 
 private:
 
-  static octave_dynamic_loader *instance;
-
-  virtual builtin_fcn
-  resolve_reference (const string& mangled_name, const string& oct_file);
-
-  string mangle_name (const string& name);
-
   // No copying!
 
   octave_dynamic_loader (const octave_dynamic_loader&);
 
   octave_dynamic_loader& operator = (const octave_dynamic_loader&);
+
+  static octave_dynamic_loader *instance;
+
+  static bool instance_ok (void);
+
+  static void make_dynamic_loader (void);
+
+protected:
+
+  virtual builtin_fcn
+  resolve_reference (const string& mangled_name, const string& oct_file);
+
+  string mangle_name (const string& name);
 };
 
 #endif
--- a/src/file-io.cc
+++ b/src/file-io.cc
@@ -49,9 +49,10 @@
 #include <unistd.h>
 #endif
 
+#include "file-ops.h"
+
 #include "defun.h"
 #include "error.h"
-#include "file-ops.h"
 #include "help.h"
 #include "lo-ieee.h"
 #include "oct-fstrm.h"
@@ -1279,7 +1280,7 @@
   octave_value retval;
 
   if (args.length () == 0)
-    retval = oct_tempnam ();
+    retval = file_ops::tempnam ();
   else
     print_usage ("tmpnam");
 
@@ -1353,7 +1354,7 @@
 	      int oct_mask = convert (mask, 8, 10);
 
 	      if (! error_state)
-		status = convert (oct_umask (oct_mask), 10, 8);
+		status = convert (file_ops::umask (oct_mask), 10, 8);
 	    }
 	}
     }
--- a/src/fn-cache.cc
+++ b/src/fn-cache.cc
@@ -26,7 +26,7 @@
 
 #include <string>
 
-#include "file-ops.h"
+#include "file-stat.h"
 #include "str-vec.h"
 
 #include <defaults.h>
@@ -84,7 +84,7 @@
   if (instance)
     retval = instance->do_list (path, no_suffix);
   else
-    panic_impossible ();
+    error ("unable to create file name cache object!");
 
   return retval;
 }
--- a/src/help.cc
+++ b/src/help.cc
@@ -41,6 +41,7 @@
 #include <unistd.h>
 #endif
 
+#include "oct-env.h"
 #include "str-vec.h"
 
 #include <defaults.h>
@@ -509,9 +510,10 @@
 
       if (! names.empty ())
 	{
-	  octave_stdout << "\n*** function files in "
-			<< make_absolute (dirs[i], Vcurrent_directory)
-			<< ":\n\n";
+	  string dir
+	    = octave_env::make_absolute (dirs[i], octave_env::getcwd ());
+
+	  octave_stdout << "\n*** function files in " << dir << ":\n\n";
 
 	  names.list_in_columns (octave_stdout);
 	}
--- a/src/lex.l
+++ b/src/lex.l
@@ -37,6 +37,8 @@
 
 #include "SLStack.h"
 
+#include "cmd-edit.h"
+
 // These would be alphabetical, but y.tab.h must be included before
 // oct-gperf.h and y.tab.h must be included after token.h and the tree
 // class declarations.  We can't include y.tab.h in oct-gperf.h
@@ -701,7 +703,7 @@
   if (! (reading_script_file || reading_fcn_file))
     {
       current_input_column = 1;
-      input_line_number = current_command_number - 1;
+      input_line_number = command_editor::current_command_number () - 1;
     }
 
   // Only ask for input from stdin if we are expecting interactive
--- a/src/load-save.cc
+++ b/src/load-save.cc
@@ -36,9 +36,10 @@
 
 #include "byte-swap.h"
 #include "data-conv.h"
+#include "file-ops.h"
+#include "glob-match.h"
 #include "lo-mappers.h"
 #include "mach-info.h"
-#include "oct-glob.h"
 #include "str-vec.h"
 
 #include "defun.h"
@@ -1662,7 +1663,7 @@
     }
   else
     {
-      string fname = oct_tilde_expand (argv[i]);
+      string fname = file_ops::tilde_expand (argv[i]);
 
       if (format == LS_UNKNOWN)
 	format = get_file_format (fname, orig_fname);
@@ -2466,7 +2467,7 @@
     }
   else
     {
-      string fname = oct_tilde_expand (argv[i]);
+      string fname = file_ops::tilde_expand (argv[i]);
 
       i++;
 
--- a/src/oct-hist.cc
+++ b/src/oct-hist.cc
@@ -48,6 +48,7 @@
 
 #include "cmd-hist.h"
 #include "file-ops.h"
+#include "oct-env.h"
 #include "str-vec.h"
 
 #include <defaults.h>
@@ -67,9 +68,6 @@
 // Nonzero means input is coming from temporary history file.
 int input_from_tmp_history_file = 0;
 
-// Guess what?
-command_history octave_command_history;
-
 // Get some default values, possibly reading them from the
 // environment.
 
@@ -77,13 +75,17 @@
 default_history_size (void)
 {
   int size = 1024;
-  char *env_size = getenv ("OCTAVE_HISTSIZE");
-  if (env_size)
+
+  string env_size = octave_env::getenv ("OCTAVE_HISTSIZE");
+
+  if (! env_size.empty ())
     {
       int val;
-      if (sscanf (env_size, "%d", &val) == 1)
+
+      if (sscanf (env_size.c_str (), "%d", &val) == 1)
 	size = val > 0 ? val : 0;
     }
+
   return size;
 }
 
@@ -92,11 +94,11 @@
 {
   string file;
 
-  char *env_file = getenv ("OCTAVE_HISTFILE");
+  string env_file = octave_env::getenv ("OCTAVE_HISTFILE");
 
-  if (env_file)
+  if (! env_file.empty ())
     {
-      fstream f (env_file, (ios::in | ios::out));
+      fstream f (env_file.c_str (), (ios::in | ios::out));
 
       if (f)
 	{
@@ -107,9 +109,11 @@
 
   if (file.empty ())
     {
-      if (! Vhome_directory.empty ())
+      string home_dir = octave_env::get_home_directory ();
+
+      if (! home_dir.empty ())
 	{
-	  file = Vhome_directory;
+	  file = home_dir;
 	  file.append ("/.octave_hist");
 	}
       else
@@ -140,25 +144,25 @@
 	{
 	  if (i < argc - 1)
 	    {
-	      string file = oct_tilde_expand (argv[i+1]);
-	      octave_command_history.set_file (file);
+	      string file = file_ops::tilde_expand (argv[i+1]);
+	      command_history::set_file (file);
 	    }
 
 	  if (option == "-a")
 	    // Append `new' lines to file.
-	    octave_command_history.append ();
+	    command_history::append ();
 
 	  else if (option == "-w")
 	    // Write entire history.
-	    octave_command_history.write ();
+	    command_history::write ();
 
 	  else if (option == "-r")
 	    // Read entire file.
-	    octave_command_history.read ();
+	    command_history::read ();
 
 	  else if (option == "-n")
 	    // Read `new' history from file.
-	    octave_command_history.read_range ();
+	    command_history::read_range ();
 
 	  else
 	    panic_impossible ();
@@ -194,7 +198,7 @@
 	limit = -limit;
     }
 
-  string_vector hlist = octave_command_history.list (limit, numbered_output);
+  string_vector hlist = command_history::list (limit, numbered_output);
 
   int len = hlist.length ();
 
@@ -267,7 +271,7 @@
 {
   if (! command.empty ())
     {
-      string_vector hlist = octave_command_history.list ();
+      string_vector hlist = command_history::list ();
 
       int len = hlist.length ();
 
@@ -275,7 +279,7 @@
 	{
 	  int i = len - 1;
 
-	  string histent = octave_command_history.get_entry (i);
+	  string histent = command_history::get_entry (i);
 
 	  if (! histent.empty ())
 	    {
@@ -287,7 +291,7 @@
 		cmd.resize (cmd_len - 1);
 
 	      if (! cmd.empty ())
-		octave_command_history.replace_entry (i, cmd);
+		command_history::replace_entry (i, cmd);
 	    }
 	}
     }
@@ -306,7 +310,7 @@
 	tmp.resize (len - 1);
 
       if (! tmp.empty ())
-	octave_command_history.add (tmp);
+	command_history::add (tmp);
     }
 }
 
@@ -316,7 +320,7 @@
 {
   string retval;
 
-  string_vector hlist = octave_command_history.list ();
+  string_vector hlist = command_history::list ();
 
   int hist_count = hlist.length ();
 
@@ -326,7 +330,7 @@
   hist_count -= 2;
 
   if (! insert_curr)
-    octave_command_history.remove (hist_count);
+    command_history::remove (hist_count);
 
   hist_count--;
 
@@ -383,7 +387,7 @@
       reverse = 1;
     }
 
-  string name = oct_tempnam ();
+  string name = file_ops::tempnam ();
 
   fstream file (name.c_str (), ios::out);
 
--- a/src/oct-hist.h
+++ b/src/oct-hist.h
@@ -30,9 +30,6 @@
 extern int default_history_size (void);
 extern string default_history_file (void);
 
-// Guess what?
-extern command_history octave_command_history;
-
 // Nonzero means input is coming from temporary history file.
 extern int input_from_tmp_history_file;
 
--- a/src/oct-stream.cc
+++ b/src/oct-stream.cc
@@ -2366,6 +2366,92 @@
 
 octave_stream_list *octave_stream_list::instance = 0;
 
+bool
+octave_stream_list::instance_ok (void)
+{
+  bool retval = true;
+
+  if (! instance)
+    instance = new octave_stream_list ();
+
+  if (! instance)
+    {
+      ::error ("unable to create stream list object!");
+
+      retval = false;
+    }
+
+  return retval;
+}
+
+octave_value
+octave_stream_list::insert (octave_base_stream *obs)
+{
+  return (instance_ok ()) ? instance->do_insert (obs) : octave_value (-1.0);
+}
+
+octave_stream *
+octave_stream_list::lookup (int fid)
+{
+  return (instance_ok ()) ? instance->do_lookup (fid) : 0;
+}
+
+octave_stream *
+octave_stream_list::lookup (const octave_value& fid)
+{
+  return (instance_ok ()) ? instance->do_lookup (fid) : 0;
+}
+
+int
+octave_stream_list::remove (int fid)
+{
+  return (instance_ok ()) ? instance->do_remove (fid) : -1;
+}
+
+int
+octave_stream_list::remove (const octave_value& fid)
+{
+  return (instance_ok ()) ? instance->do_remove (fid) : -1;
+}
+
+void
+octave_stream_list::clear (void)
+{
+  if (instance)
+    instance->do_clear ();
+}
+
+string_vector
+octave_stream_list::get_info (int fid)
+{
+  return (instance_ok ()) ? instance->do_get_info (fid) : string_vector ();
+}
+
+string_vector
+octave_stream_list::get_info (const octave_value& fid)
+{
+  return (instance_ok ()) ? instance->do_get_info (fid) : string_vector ();
+}
+
+string
+octave_stream_list::list_open_files (void)
+{
+  return (instance_ok ()) ? instance->do_list_open_files () : string ();
+}
+
+octave_value
+octave_stream_list::open_file_numbers (void)
+{
+  return (instance_ok ())
+    ? instance->do_open_file_numbers () : octave_value ();
+}
+
+int
+octave_stream_list::get_file_number (const octave_value& fid)
+{
+  return (instance_ok ()) ? instance->do_get_file_number (fid) : -1;
+}
+
 octave_value
 octave_stream_list::do_insert (octave_base_stream *obs)
 {
@@ -2410,22 +2496,6 @@
   return octave_value (os, stream_number);
 }
 
-octave_value
-octave_stream_list::insert (octave_base_stream *obs)
-{
-  octave_value retval = -1.0;
-
-  if (! instance)
-    instance = new octave_stream_list ();
-
-  if (instance)
-    retval = instance->do_insert (obs);
-  else
-    panic_impossible ();
-
-  return retval;
-}
-
 octave_stream *
 octave_stream_list::do_lookup (int fid) const
 {
@@ -2450,28 +2520,6 @@
   return retval;
 }
 
-octave_stream *
-octave_stream_list::lookup (int fid)
-{
-  octave_stream *retval = 0;
-
-  if (instance)
-    retval = instance->do_lookup (fid);
-
-  return retval;
-}
-
-octave_stream *
-octave_stream_list::lookup (const octave_value& fid)
-{
-  octave_stream *retval = 0;
-
-  if (instance)
-    retval = instance->do_lookup (fid);
-
-  return retval;
-}
-
 int
 octave_stream_list::do_remove (int fid)
 {
@@ -2507,28 +2555,6 @@
   return retval;
 }
 
-int
-octave_stream_list::remove (int fid)
-{
-  int retval = -1;
-
-  if (instance)
-    retval = instance->do_remove (fid);
-
-  return retval;
-}
-
-int
-octave_stream_list::remove (const octave_value& fid)
-{
-  int retval = -1;
-
-  if (instance)
-    retval = instance->do_remove (fid);
-
-  return retval;
-}
-
 void
 octave_stream_list::do_clear (void)
 {
@@ -2549,13 +2575,6 @@
     }
 }
 
-void
-octave_stream_list::clear (void)
-{
-  if (instance)
-    instance->do_clear ();
-}
-
 string_vector
 octave_stream_list::do_get_info (int fid) const
 {
@@ -2594,28 +2613,6 @@
   return retval;
 }
 
-string_vector
-octave_stream_list::get_info (int fid)
-{
-  string_vector retval;
-
-  if (instance)
-    retval = instance->do_get_info (fid);
-
-  return retval;
-}
-
-string_vector
-octave_stream_list::get_info (const octave_value& fid)
-{
-  string_vector retval;
-
-  if (instance)
-    retval = instance->do_get_info (fid);
-
-  return retval;
-}
-
 string
 octave_stream_list::do_list_open_files (void) const
 {
@@ -2658,17 +2655,6 @@
   return retval;
 }
 
-string
-octave_stream_list::list_open_files (void)
-{
-  string retval;
-
-  if (instance)
-    retval = instance->do_list_open_files ();
-
-  return retval;
-}
-
 octave_value
 octave_stream_list::do_open_file_numbers (void) const
 {
@@ -2689,17 +2675,6 @@
   return retval;
 }
 
-octave_value
-octave_stream_list::open_file_numbers (void)
-{
-  octave_value retval;
-
-  if (instance)
-    retval = instance->do_open_file_numbers ();
-
-  return retval;
-}
-
 int
 octave_stream_list::do_get_file_number (const octave_value& fid) const
 {
@@ -2737,17 +2712,6 @@
   return retval;
 }
 
-int
-octave_stream_list::get_file_number (const octave_value& fid)
-{
-  int retval = -1;
-
-  if (instance)
-    retval = instance->do_get_file_number (fid);
-
-  return retval;
-}
-
 /*
 ;;; Local Variables: ***
 ;;; mode: C++ ***
--- a/src/oct-stream.h
+++ b/src/oct-stream.h
@@ -494,6 +494,8 @@
 
   ~octave_stream_list (void) { }
 
+  static bool instance_ok (void);
+
   static octave_value insert (octave_base_stream *obs);
 
   static octave_stream *lookup (int fid);
--- a/src/octave.cc
+++ b/src/octave.cc
@@ -43,11 +43,10 @@
 #include <unistd.h>
 #endif
 
-#ifdef HAVE_PWD_H
-#include <pwd.h>
-#endif
-
+#include "cmd-edit.h"
+#include "file-stat.h"
 #include "lo-error.h"
+#include "oct-env.h"
 #include "str-vec.h"
 
 #include <defaults.h>
@@ -55,7 +54,6 @@
 #include "dynamic-ld.h"
 #include "error.h"
 #include "file-io.h"
-#include "file-ops.h"
 #include "help.h"
 #include "input.h"
 #include "lex.h"
@@ -92,11 +90,6 @@
 char *program_invocation_short_name;
 #endif
 
-#if defined (USE_READLINE)
-// This is from readline's paren.c:
-extern int rl_blink_matching_paren;
-#endif
-
 // The command-line options.
 static string_vector octave_argv;
 
@@ -169,6 +162,18 @@
 static void
 intern_argv (int argc, char **argv)
 {
+  octave_env::set_program_name (argv[0]);
+
+  // XXX FIXME XXX -- Kpathsea needs this.
+
+#if ! defined (HAVE_PROGRAM_INVOCATION_NAME)
+  program_invocation_name
+    = strsave (octave_env::get_program_invocation_name () . c_str ());
+
+  program_invocation_short_name
+    = strsave (octave_env::get_program_name () . c_str ());
+#endif
+
   if (argc > 1)
     {
       // Skip program name in argv.
@@ -182,62 +187,28 @@
   bind_builtin_variable ("nargin", static_cast<double> (argc-1), 1, 1, 0);
 }
 
-// Initialize some global variables for later use.
-
-static void
-initialize_globals (const string& name)
-{
-  // Kpathsea needs this.
-
-#if ! defined (HAVE_PROGRAM_INVOCATION_NAME)
-  program_invocation_name = strsave (name.c_str ());
-  program_invocation_short_name = strrchr (program_invocation_name, '/');
-  if (! program_invocation_short_name)
-    program_invocation_short_name = program_invocation_name;
-#endif
-
-  Vprogram_invocation_name = name;
-  size_t pos = Vprogram_invocation_name.rfind ('/');
-  Vprogram_name = (pos == NPOS)
-    ? Vprogram_invocation_name : Vprogram_invocation_name.substr (pos+1);
-
-  struct passwd *entry = getpwuid (getuid ());
-  Vuser_name = entry ? entry->pw_name : "I have no name!";
-
-  char hostname[256];
-  int status = gethostname (hostname, 255);
-  Vhost_name = (status < 0) ? "I have no host!" : hostname;
-
-  char *hd = getenv ("HOME");
-  Vhome_directory = hd ? hd : "I have no home!";
-
-  install_defaults ();
-}
-
 static void
 initialize_pathsearch (void)
 {
   // This may seem odd, but doing it this way means that we don't have
   // to modify the kpathsea library...
 
-  char *odb = getenv ("OCTAVE_DB_DIR");
+  string odb = octave_env::getenv ("OCTAVE_DB_DIR");
 
-  if (odb)
-    oct_putenv ("TEXMF", odb);
-  else
+  if (odb.empty ())
     {
-      char *oh = getenv ("OCTAVE_HOME");
+      string oh = octave_env::getenv ("OCTAVE_HOME");
 
-      if (oh)
+      if (oh.empty ())
+	octave_env::putenv ("TEXMF", OCTAVE_DATADIR "/octave");
+      else  
 	{
-	  int len = strlen (oh) + 12;
-	  char *putenv_val = new char [len];
-	  sprintf (putenv_val, "%s/lib/octave", oh);
-	  oct_putenv ("TEXMF", putenv_val);
+	  oh.append ("/lib/octave");
+	  octave_env::putenv ("TEXMF", oh);
 	}
-      else  
-	oct_putenv ("TEXMF", OCTAVE_DATADIR "/octave");
     }
+  else
+    octave_env::putenv ("TEXMF", odb);
 }
 
 // Initialize by reading startup files.
@@ -276,15 +247,17 @@
 
       int home_rc_already_executed = 0;
 
-      const char *initfile = getenv ("OCTAVE_INITFILE");
+      string initfile = octave_env::getenv ("OCTAVE_INITFILE");
 
-      if (! initfile)
+      if (initfile.empty ())
 	initfile = ".octaverc";
 
-      string home_rc = Vhome_directory + "/" + initfile;
+      string home_dir = octave_env::get_home_directory ();
+
+      string home_rc = home_dir + "/" + initfile;
       string local_rc = string ("./") + initfile;
 
-      if (! Vhome_directory.empty ())
+      if (! home_dir.empty ())
 	{
 	  parse_and_execute (home_rc, verbose);
 
@@ -396,7 +369,7 @@
 main (int argc, char **argv)
 {
   // The order of these calls is important.  The call to
-  // initialize_globals must come before install_builtins because
+  // install_defaults must come before install_builtins because
   // default variable values must be available for the varaibles to be
   // installed, and the call to install_builtins must come before the
   // options are processed because some command line options override
@@ -406,7 +379,7 @@
 
   initialize_error_handlers ();
 
-  initialize_globals (argv[0]);
+  install_defaults ();
 
   initialize_pathsearch ();
 
@@ -491,7 +464,7 @@
 	  break;
 
 	case NO_LINE_EDITING_OPTION:
-	  using_readline = false;
+	  line_editing = 0;
 	  break;
 
 	case NO_SITE_FILE_OPTION:
@@ -521,7 +494,7 @@
   // These can come after command line args since none of them set any
   // defaults that might be changed by command line options.
 
-  initialize_readline ();
+  initialize_command_input ();
 
   if (! inhibit_startup_message)
     cout << OCTAVE_STARTUP_MESSAGE "\n" << endl;
@@ -531,14 +504,14 @@
 
   execute_startup_files ();
 
-  octave_command_history.read (false);
+  command_history::read (false);
 
   if (! inhibit_startup_message && reading_startup_message_printed)
     cout << endl;
 
   // Avoid counting commands executed from startup files.
 
-  current_command_number = 1;
+  command_editor::reset_current_command_number (1);
 
   // If there is an extra argument, see if it names a file to read.
   // Additional arguments are taken as command line options for the
@@ -570,7 +543,8 @@
 
 	  intern_argv (remaining_args, argv+last_arg_idx);
 
-	  rl_blink_matching_paren = 0;
+	  command_editor::blink_matching_paren (false);
+
 	  switch_to_buffer (create_buffer (infile));
 	}
       else
@@ -593,7 +567,7 @@
 
   if (! interactive && forced_interactive)
     {
-      rl_blink_matching_paren = 0;
+      command_editor::blink_matching_paren (false);
 
       // XXX FIXME XXX -- is this the right thing to do?
 
@@ -602,7 +576,7 @@
     }
 
   if (! interactive)
-    using_readline = 0;
+    line_editing = 0;
 
   int retval = main_loop ();
 
--- a/src/ov-typeinfo.cc
+++ b/src/ov-typeinfo.cc
@@ -56,13 +56,28 @@
 template class Array<type_conv_fcn>;
 template class Array2<type_conv_fcn>;
 
+bool
+octave_value_typeinfo::instance_ok (void)
+{
+  bool retval = true;
+  if (! instance)
+    instance = new octave_value_typeinfo ();
+
+  if (! instance)
+    {
+      ::error ("unable to create value type info object!");
+
+      retval = false;
+    }
+
+  return retval;
+}
+
 int
 octave_value_typeinfo::register_type (const string& name)
 {
-  if (! instance)
-    instance = new octave_value_typeinfo ();
-
-  return instance->do_register_type (name);
+  return (instance_ok ())
+    ? instance->do_register_type (name) : -1;
 }
 
 bool
@@ -70,10 +85,8 @@
 					   int t1, int t2,
 					   binary_op_fcn f)
 {
-  if (! instance)
-    instance = new octave_value_typeinfo ();
-
-  return instance->do_register_binary_op (op, t1, t2, f);
+  return (instance_ok ())
+    ? instance->do_register_binary_op (op, t1, t2, f) : false;
 }
 
 bool
@@ -81,30 +94,24 @@
 					   int t_lhs, int t_rhs,
 					   assign_op_fcn f)
 {
-  if (! instance)
-    instance = new octave_value_typeinfo ();
-
-  return instance->do_register_assign_op (op, t_lhs, t_rhs, f);
+  return (instance_ok ())
+    ? instance->do_register_assign_op (op, t_lhs, t_rhs, f) : -1;
 }
 
 bool
 octave_value_typeinfo::register_pref_assign_conv (int t_lhs, int t_rhs,
 						  int t_result) 
 {
-  if (! instance)
-    instance = new octave_value_typeinfo ();
-
-  return instance->do_register_pref_assign_conv (t_lhs, t_rhs, t_result);
+  return (instance_ok ())
+    ? instance->do_register_pref_assign_conv (t_lhs, t_rhs, t_result) : false;
 }
 
 bool
 octave_value_typeinfo::register_widening_op (int t, int t_result,
 					     type_conv_fcn f)
 {
-  if (! instance)
-    instance = new octave_value_typeinfo ();
-
-  return instance->do_register_widening_op (t, t_result, f);
+  return (instance_ok ())
+    ? instance->do_register_widening_op (t, t_result, f) : false;
 }
 
 int
--- a/src/ov-typeinfo.h
+++ b/src/ov-typeinfo.h
@@ -42,6 +42,8 @@
 {
 public:
 
+  static bool instance_ok (void);
+
   static int register_type (const string&);
 
   static bool register_binary_op (octave_value::binary_op, int, int,
--- a/src/pager.cc
+++ b/src/pager.cc
@@ -29,7 +29,8 @@
 #include <string>
 #include <fstream.h>
 
-#include "oct-term.h"
+#include "cmd-edit.h"
+#include "oct-env.h"
 
 #include "procstream.h"
 
@@ -190,7 +191,7 @@
 {
   if (s)
     {
-      int available_rows = terminal_rows () - 2;
+      int available_rows = command_editor::terminal_rows () - 2;
 
       int count = 0;
 
@@ -271,7 +272,7 @@
 {
   if (! instance)
     instance = new octave_pager_stream ();
-      
+
   return *instance;
 }
 
@@ -432,14 +433,10 @@
 static string
 default_pager (void)
 {
-  string pager_binary;
-
-  char *pgr = getenv ("PAGER");
+  string pager_binary = octave_env::getenv ("PAGER");
 
-  if (pgr)
-    pager_binary = string (pgr);
 #ifdef DEFAULT_PAGER
-  else
+  if (pager_binary.empty ())
     {
       pager_binary = string (DEFAULT_PAGER);
 
@@ -447,7 +444,8 @@
 	{
 	  pager_binary.append (" -e");
 
-	  if (! getenv ("LESS"))
+	  string lessflags = octave_env::getenv ("LESS");
+	  if (lessflags.empty ())
 	    pager_binary.append
 	      (" -P'-- less ?pB(%pB\\%):--. (f)orward, (b)ack, (q)uit$'");
 	}
--- a/src/pr-output.cc
+++ b/src/pr-output.cc
@@ -35,12 +35,12 @@
 
 #include "CMatrix.h"
 #include "Range.h"
+#include "cmd-edit.h"
 #include "dMatrix.h"
 #include "lo-mappers.h"
 #include "mach-info.h"
 #include "oct-cmplx.h"
 #include "oct-math.h"
-#include "oct-term.h"
 #include "str-vec.h"
 
 #include "defun.h"
@@ -1146,7 +1146,7 @@
       set_format (m, fw);
       int column_width = fw + 2;
       int total_width = nc * column_width;
-      int max_width = terminal_columns ();
+      int max_width = command_editor::terminal_cols ();
 
       if (pr_as_read_syntax)
 	max_width -= 4;
@@ -1299,7 +1299,7 @@
       int column_width = i_fw + r_fw;
       column_width += (bank_format || hex_format|| bit_format) ? 2 : 7;
       int total_width = nc * column_width;
-      int max_width = terminal_columns ();
+      int max_width = command_editor::terminal_cols ();
 
       if (pr_as_read_syntax)
 	max_width -= 4;
@@ -1447,7 +1447,7 @@
 	{
 	  int column_width = fw + 2;
 	  int total_width = num_elem * column_width;
-	  int max_width = terminal_columns ();
+	  int max_width = command_editor::terminal_cols ();
 
 	  if (free_format)
 	    {
--- a/src/pt-plot.cc
+++ b/src/pt-plot.cc
@@ -700,7 +700,7 @@
 
 	      int n_max = 0;
 
-	      file = oct_tilde_expand (data.string_value ());
+	      file = file_ops::tilde_expand (data.string_value ());
 
 	      ifstream ftmp (file.c_str ());
 
@@ -850,7 +850,7 @@
 string
 save_in_tmp_file (octave_value& t, int ndim, bool parametric)
 {
-  string name = oct_tempnam ();
+  string name = file_ops::tempnam ();
 
   if (! name.empty ())
     {
--- a/src/sighandlers.cc
+++ b/src/sighandlers.cc
@@ -569,6 +569,52 @@
 
 octave_child_list *octave_child_list::instance = 0;
 
+bool
+octave_child_list::instance_ok (void)
+{
+  bool retval = true;
+
+  if (! instance)
+    instance = new octave_child_list ();
+
+  if (! instance)
+    {
+      ::error ("unable to create child list object!");
+
+      retval = false;
+    }
+
+  return retval;
+}
+
+void
+octave_child_list::insert (pid_t pid, octave_child::dead_child_handler f)
+{
+  if (instance_ok ())
+    instance->do_insert (pid, f);
+}
+
+void
+octave_child_list::remove (pid_t pid)
+{
+  if (instance_ok ())
+    instance->do_remove (pid);
+}
+
+int
+octave_child_list::length (void)
+{
+  return (instance_ok ()) ? instance->do_length () : 0;
+}
+
+octave_child&
+octave_child_list::elem (int i)
+{
+  static octave_child foo;
+
+  return (instance_ok ()) ? instance->do_elem (i) : foo;
+}
+
 void
 octave_child_list::do_insert (pid_t pid, octave_child::dead_child_handler f)
 {
@@ -607,18 +653,6 @@
 }
 
 void
-octave_child_list::insert (pid_t pid, octave_child::dead_child_handler f)
-{
-  if (! instance)
-    instance = new octave_child_list ();
-
-  if (instance)
-    instance->do_insert (pid, f);
-  else
-    panic_impossible ();
-}
-
-void
 octave_child_list::do_remove (pid_t pid)
 {
   // Mark the record for PID invalid.
@@ -635,16 +669,23 @@
     }
 }
 
-void
-octave_child_list::remove (pid_t pid)
+int
+octave_child_list::do_length (void) const
+{
+  return curr_len;
+}
+
+octave_child&
+octave_child_list::do_elem (int i)
 {
-  if (! instance)
-    instance = new octave_child_list ();
+  static octave_child foo;
+
+  int n = do_length ();
 
-  if (instance)
-    instance->do_remove (pid);
+  if (i >= 0 && i < n)
+    return list (i);
   else
-    panic_impossible ();
+    return foo;
 }
 
 /*
--- a/src/sighandlers.h
+++ b/src/sighandlers.h
@@ -148,26 +148,15 @@
 
   ~octave_child_list (void) { }
 
+  static bool instance_ok (void);
+
   static void insert (pid_t pid, octave_child::dead_child_handler f);
 
   static void remove (pid_t pid);
 
-  static int length (void) { return instance ? instance->curr_len : 0; }
-
-  static octave_child& elem (int i)
-    {
-      static octave_child foo;
+  static int length (void);
 
-      if (instance)
-	{
-	  int n = length ();
-
-	  if (i >= 0 && i < n)
-	    return instance->list (i);
-	}
-
-      return foo;
-    }
+  static octave_child& elem (int i);
 
 private:
 
@@ -180,6 +169,10 @@
   void do_insert (pid_t pid, octave_child::dead_child_handler f);
 
   void do_remove (pid_t pid);
+
+  int do_length (void) const;
+
+  octave_child& do_elem (int i);
 };
 
 #endif
--- a/src/symtab.cc
+++ b/src/symtab.cc
@@ -30,7 +30,7 @@
 
 #include <cctype>
 
-#include "oct-glob.h"
+#include "glob-match.h"
 #include "str-vec.h"
 
 #include "error.h"
--- a/src/syscalls.cc
+++ b/src/syscalls.cc
@@ -44,9 +44,11 @@
 #include <fcntl.h>
 #endif
 
+#include "file-ops.h"
+#include "file-stat.h"
+
 #include "defun.h"
 #include "error.h"
-#include "file-ops.h"
 #include "gripes.h"
 #include "help.h"
 #include "lo-utils.h"
@@ -473,7 +475,7 @@
 
   if (args.length () == 1)
     {
-      string fname = oct_tilde_expand (args(0).string_value ());
+      string fname = file_ops::tilde_expand (args(0).string_value ());
 
       if (! error_state)
 	{
@@ -526,7 +528,7 @@
 
 	      string msg;
 
-	      int status = oct_mkfifo (name, mode, msg);
+	      int status = file_ops::mkfifo (name, mode, msg);
 
 	      retval(0) = static_cast<double> (status);
 
@@ -633,7 +635,7 @@
 
   if (args.length () == 1)
     {
-      string fname = oct_tilde_expand (args(0).string_value ());
+      string fname = file_ops::tilde_expand (args(0).string_value ());
 
       if (! error_state)
 	{
@@ -682,7 +684,7 @@
 
 	  string msg;
 
-	  int status = oct_unlink (name, msg);
+	  int status = file_ops::unlink (name, msg);
 
 	  retval(0) = static_cast<double> (status);
 
--- a/src/sysdep.cc
+++ b/src/sysdep.cc
@@ -71,16 +71,11 @@
 #include <sys/utsname.h>
 #endif
 
-#if defined (USE_READLINE)
-#include <readline/readline.h>
-#include <readline/tilde.h>
-#endif
-
-extern char *term_clrpag;
-extern "C" void _rl_output_character_function ();
-
+#include "cmd-edit.h"
+#include "file-ops.h"
 #include "lo-mappers.h"
 #include "mach-info.h"
+#include "oct-env.h"
 #include "oct-math.h"
 
 #include "defun.h"
@@ -88,7 +83,6 @@
 #include "help.h"
 #include "input.h"
 #include "oct-obj.h"
-#include "pathlen.h"
 #include "ov.h"
 #include "sysdep.h"
 #include "toplev.h"
@@ -122,9 +116,7 @@
   if (code == 5)
     warning ("hopefully recoverable malloc error: freeing wild pointer");
   else
-    {
-      panic ("probably irrecoverable malloc error: code %d", code);
-    }
+    panic ("probably irrecoverable malloc error: code %d", code);
 }
 
 static void
@@ -357,70 +349,12 @@
   return c;
 }
 
-string
-octave_getcwd (void)
-{
-  string retval;
-  char buf[MAXPATHLEN];
-
-#if defined (__EMX__)
-  char *tmp = _getcwd2 (buf, MAXPATHLEN);
-#else
-  char *tmp = getcwd (buf, MAXPATHLEN);
-#endif
-
-  if (tmp)
-    retval = tmp;
-
-  return retval;
-}
-
-int
-octave_chdir (const string& path)
-{
-#if defined (__EMX__)
-  int retval = -1;
-
-  char *tmp_path = strsave (path.c_str ());
-
-  if (path.length () == 2 && path[1] == ':')
-    {
-      char *upper_case_dir_name = strupr (tmp_path);
-      _chdrive (upper_case_dir_name[0]);
-      if (_getdrive () == upper_case_dir_name[0])
-	retval = _chdir2 ("/");
-    }
-  else
-    retval = _chdir2 (tmp_path);
-
-  delete [] tmp_path;
-
-  return retval;
-#else
-  return chdir (path.c_str ());
-#endif
-}
-
 DEFUN (clc, , ,
   "clc (): clear screen")
 {
-  octave_value_list retval;
-
-  rl_beg_of_line ();
-  rl_kill_line (1);
+  command_editor::clear_screen ();
 
-#if ! defined (_GO32_)
-  if (term_clrpag)
-    tputs (term_clrpag, 1, _rl_output_character_function);
-  else
-    crlf ();
-#else
-  crlf ();
-#endif
-
-  fflush (rl_outstream);
-
-  return retval;
+  return octave_value_list ();
 }
 
 DEFALIAS (home, clc);
@@ -434,17 +368,10 @@
 
   if (nargin == 1)
     {
-      string tstr = args(0).string_value ();
-      const char *name = tstr.c_str ();
+      string name = args(0).string_value ();
 
       if (! error_state)
-	{
-	  char *value = getenv (name);
-	  if (value)
-	    retval = value;
-	  else
-	    retval = "";
-	}
+	retval = octave_env::getenv (name);
     }
   else
     print_usage ("getenv");
@@ -468,7 +395,7 @@
 	  string val = args(1).string_value (); 
 
 	  if (! error_state)
-	    oct_putenv (var.c_str (), val.c_str ());
+	    octave_env::putenv (var, val);
 	  else
 	    error ("putenv: second argument should be a string");
 	}
@@ -612,66 +539,6 @@
 			      || flt_fmt == oct_mach_info::ieee_big_endian);
 }
 
-#if !defined (HAVE_GETHOSTNAME) && defined (HAVE_SYS_UTSNAME_H)
-int
-gethostname (char *name, int namelen)
-{
-  int i;
-  struct utsname ut;
-
-  --namelen;
-
-  uname (&ut);
-  i = strlen (ut.nodename) + 1;
-  strncpy (name, ut.nodename, i < namelen ? i : namelen);
-  name[namelen] = '\0';
-
-  return 0;
-}
-#endif
-
-// The check for error state allows us to do this:
-//
-//   string foo = oct_tilde_expand (args(0).string_value ());
-//
-// without having to use a temporary and check error_state before
-// calling oct_tilde_expand.
-
-string
-oct_tilde_expand (const string& name)
-{
-  string retval;
-
-  if (! error_state)
-    {
-      char *tmp = tilde_expand (name.c_str ());
-      retval = tmp;
-      delete [] tmp;
-    }
-
-  return retval;
-}
-
-// A vector version of the above.
-
-string_vector
-oct_tilde_expand (const string_vector& names)
-{
-  string_vector retval;
-
-  if (! error_state)
-    {
-      int n = names.length ();
-
-      retval.resize (n);
-
-      for (int i = 0; i < n; i++)
-	retval[i] = oct_tilde_expand (names[i]);
-    }
-
-  return retval;
-}
-
 DEFUN (tilde_expand, args, ,
   "tilde_expand (STRING): perform tilde expansion on STRING")
 {
@@ -680,7 +547,7 @@
   int nargin = args.length ();
 
   if (nargin == 1)
-    retval = oct_tilde_expand (args(0).all_strings ());
+    retval = file_ops::tilde_expand (args(0).all_strings ());
   else
     print_usage ("tilde_expand");
 
@@ -690,7 +557,7 @@
 #if defined (__EMX__) && defined (OS2)
 
 DEFUN_TEXT (extproc, , ,
-  "extproc : ignored by Octave")
+  "extproc: ignored by Octave")
 {
   return octave_value_list ();
 }
--- a/src/sysdep.h
+++ b/src/sysdep.h
@@ -26,22 +26,13 @@
 #include <string>
 
 #include "lo-ieee.h"
+#include "lo-sysdep.h"
 
 extern void sysdep_init (void);
 
 extern void raw_mode (int);
 extern int kbhit (void);
 
-extern string octave_getcwd (void);
-extern int octave_chdir (const string&);
-
-#if !defined (HAVE_GETHOSTNAME) && defined (HAVE_SYS_UTSNAME_H)
-extern int gethostname (char *, int);
-#endif
-
-extern string oct_tilde_expand (const string&);
-extern string_vector oct_tilde_expand (const string_vector&);
-
 #endif
 
 /*
--- a/src/toplev.cc
+++ b/src/toplev.cc
@@ -44,6 +44,8 @@
 #include <unistd.h>
 #endif
 
+#include "cmd-edit.h"
+#include "file-ops.h"
 #include "lo-error.h"
 #include "lo-mappers.h"
 #include "str-vec.h"
@@ -77,21 +79,6 @@
 #include "variables.h"
 #include <version.h>
 
-// argv[0] for this program.
-string Vprogram_invocation_name;
-
-// Cleaned-up name of this program, not including path information.
-string Vprogram_name;
-
-// Login name for user running this program.
-string Vuser_name;
-
-// Name of the host we are running on.
-string Vhost_name;
-
-// User's home directory.
-string Vhome_directory;
-
 // Nonzero means we print 
 static bool Vdefault_eval_print_flag = true;
 
@@ -103,16 +90,7 @@
 
 // Nonzero means we are using readline.
 // (--no-line-editing)
-#if defined (USE_READLINE)
-int using_readline = 1;
-#else
-int using_readline = 0;
-#endif
-
-#if defined (USE_READLINE)
-// This is from readline's rltty.c:
-extern "C" void rl_deprep_terminal (void);
-#endif
+int line_editing = 1;
 
 // Nonzero means we printed messages about reading startup files.
 int reading_startup_message_printed = 0;
@@ -152,10 +130,10 @@
 
   switch_to_buffer (new_buf);
 
-  unwind_protect_int (using_readline);
+  unwind_protect_int (line_editing);
   unwind_protect_int (input_from_command_line_file);
 
-  using_readline = 0;
+  line_editing = 0;
   input_from_command_line_file = 0;
 
   unwind_protect_ptr (curr_sym_tab);
@@ -336,7 +314,7 @@
 
       if (! error_state)
 	{
-	  file = oct_tilde_expand (file);
+	  file = file_ops::tilde_expand (file);
 
 	  parse_and_execute (file, false, "source");
 
@@ -357,13 +335,12 @@
 void
 clean_up_and_exit (int retval)
 {
-#if defined (USE_READLINE)
-  rl_deprep_terminal ();
-#else
+  command_editor::restore_terminal_state ();
+
+  // XXX FIXME XXX -- is this needed?  Can it cause any trouble?
   raw_mode (0);
-#endif
 
-  octave_command_history.clean_up_and_save ();
+  command_history::clean_up_and_save ();
 
   close_plot_stream ();
 
--- a/src/toplev.h
+++ b/src/toplev.h
@@ -52,30 +52,12 @@
 extern void
 do_octave_atexit (void);
 
-// argv[0] for this program.
-extern string Vprogram_invocation_name;
-
-// Cleaned-up name of this program, not including path information.
-extern string Vprogram_name;
-
-// Login name for user running this program.
-extern string Vuser_name;
-
-// Name of the host we are running on.
-extern string Vhost_name;
-
-// Home directory for the current user.
-extern string Vhome_directory;
-
 // Nonzero means we are using readline.
-extern int using_readline;
+extern int line_editing;
 
 // Nonzero means we printed messages about reading startup files.
 extern int reading_startup_message_printed;
 
-// Command number, counting from the beginning of this session.
-extern int current_command_number;
-
 // Nonzero means we are exiting via the builtin exit or quit functions.
 extern int quitting_gracefully;
 
--- a/src/utils.cc
+++ b/src/utils.cc
@@ -57,8 +57,9 @@
 
 #include "SLStack.h"
 
-#include "file-ops.h"
+#include "file-stat.h"
 #include "oct-cmplx.h"
+#include "oct-env.h"
 #include "str-vec.h"
 
 #include <defaults.h>
@@ -82,20 +83,6 @@
 // Top level context (?)
 extern jmp_buf toplevel;
 
-// Save a string.
-
-char *
-strsave (const char *s)
-{
-  if (! s)
-    return 0;
-
-  int len = strlen (s);
-  char *tmp = new char [len+1];
-  tmp = strcpy (tmp, s);
-  return tmp;
-}
-
 // Return to the main command loop in octave.cc.
 
 extern "C" void
@@ -245,7 +232,7 @@
 {
   dir_path p (path);
 
-  return make_absolute (p.find (name), Vcurrent_directory);
+  return octave_env::make_absolute (p.find (name), octave_env::getcwd ());
 }
 
 DEFUN (file_in_path, args, ,
@@ -283,9 +270,6 @@
   if (! suffix.empty ())
     nm.append (suffix);
 
-  if (Vcurrent_directory.empty ())
-    get_working_directory ("file_in_path");
-
   return search_path_for_file (Vload_path, nm);
 }
 
@@ -403,91 +387,6 @@
   return retval;
 }
 
-// This function was adapted from xputenv from Karl Berry's kpathsearch
-// library.
-
-void
-oct_putenv (const char *var_name, const char *value)
-{
-  static const char **saved_env_items = 0;
-  static unsigned saved_len;
-  char *old_item = 0;
-
-  int new_len = strlen (var_name) + strlen (value) + 2;
-
-  char *new_item = new char [new_len];
-
-  sprintf (new_item, "%s=%s", var_name, value);
-
-#ifndef SMART_PUTENV
-
-  // Check if we have saved anything yet.
-
-  if (! saved_env_items)
-    {
-      saved_env_items = new const char * [1];
-      saved_env_items[0] = var_name;
-      saved_len = 1;
-    }
-  else
-    {
-      // Check if we've assigned VAR_NAME before.
-
-      unsigned len = strlen (var_name);
-
-      for (unsigned i = 0; i < saved_len && ! old_item; i++)
-        {
-          if (strcmp (saved_env_items[i], var_name) == 0)
-            {
-              old_item = getenv (var_name);
-
-              assert (old_item);
-
-              // Back up to the `NAME=' in the environment before the
-	      // value that getenv returns.
-
-              old_item -= (len + 1);
-            }
-        }
-      
-      if (! old_item)
-        {
-          // If we haven't seen VAR_NAME before, save it.  Assume it
-	  // is in safe storage.
-
-          saved_len++;
-
-	  const char **tmp = new const char * [saved_len];
-
-	  for (unsigned i = 0; i < saved_len - 1; i++)
-	    tmp[i] = saved_env_items[i];
-
-	  tmp[saved_len - 1] = var_name;
-
-          delete [] saved_env_items;
-
-	  saved_env_items = tmp;
-        }
-    }
-
-#endif
-
-  // As far as I can see there's no way to distinguish between the
-  // various errors; putenv doesn't have errno values.
-
-  if (putenv (new_item) < 0)
-    error ("putenv (%s) failed", new_item);
-  
-#ifndef SMART_PUTENV
-
-  // Can't free `new_item' because its contained value is now in
-  // `environ', but we can free `old_item', since it's been replaced.
-
-  delete [] old_item;
-
-#endif
-}
-
 static void
 warn_old_style_preference (bool val, const string& sval)
 {
--- a/src/utils.h
+++ b/src/utils.h
@@ -33,8 +33,6 @@
 class octave_value_list;
 class string_vector;
 
-extern char *strsave (const char *);
-
 extern string search_path_for_file (const string&, const string&);
 extern string file_in_path (const string&, const string&);
 extern string fcn_file_in_path (const string&);
@@ -56,8 +54,6 @@
 
 extern string undo_string_escapes (const string& s);
 
-extern void oct_putenv (const char *, const char *);
-
 extern int check_preference (const string& var);
 
 #endif
--- a/src/variables.cc
+++ b/src/variables.cc
@@ -41,13 +41,13 @@
 #include <unistd.h>
 #endif
 
-#if defined (USE_READLINE)
-#include <readline/readline.h>
-#endif
-
+#include "cmd-edit.h"
+#include "cmd-hist.h"
 #include "file-ops.h"
+#include "file-stat.h"
 #include "lo-mappers.h"
-#include "oct-glob.h"
+#include "oct-env.h"
+#include "glob-match.h"
 #include "str-vec.h"
 
 #include <defaults.h>
@@ -55,27 +55,23 @@
 #include "dirfns.h"
 #include "dynamic-ld.h"
 #include "error.h"
-#include "file-io.h"
 #include "fn-cache.h"
 #include "gripes.h"
 #include "help.h"
 #include "input.h"
 #include "lex.h"
-#include "load-save.h"
+#include "sysdep.h"
 #include "oct-hist.h"
-#include "toplev.h"
+#include "oct-map.h"
+#include "oct-mapper.h"
+#include "oct-obj.h"
+#include "oct-sym.h"
+#include "ov.h"
 #include "pager.h"
 #include "parse.h"
-#include "symtab.h"
-#include "sysdep.h"
-#include "oct-sym.h"
-#include "oct-builtin.h"
-#include "oct-mapper.h"
-#include "oct-usr-fcn.h"
-#include "oct-obj.h"
 #include "pt-id.h"
 #include "pt-indir.h"
-#include "pr-output.h"
+#include "symtab.h"
 #include "toplev.h"
 #include "unwind-prot.h"
 #include "utils.h"
@@ -586,13 +582,12 @@
 // Is there a corresponding function file that is newer than the
 // symbol definition?
 
-static int
+static bool
 symbol_out_of_date (symbol_record *sr)
 {
-  if (Vignore_function_time_stamp == 2)
-    return 0;
+  bool retval = false;
 
-  if (sr)
+  if (Vignore_function_time_stamp != 2 && sr)
     {
       octave_symbol *ans = sr->def ();
       if (ans)
@@ -606,19 +601,22 @@
 
 	      string fname = fcn_file_in_path (ff);
 
-	      int status = is_newer (fname, tp);
+	      int status = file_stat::is_newer (fname, tp);
 
 	      if (status > 0)
-		return 1;
+		retval = true;
 	    }
 	}
     }
-  return 0;
+
+  return retval;
 }
 
-static int
+static bool
 looks_like_octave_copyright (const string& s)
 {
+  bool retval = false;
+
   string t = s.substr (0, 15);
 
   if (t == " Copyright (C) ")
@@ -637,11 +635,12 @@
 
 	      if (t == " This file is part of Octave."
 		  || t == " This program is free softwar")
-		return 1;
+		retval = true;
 	    }
 	}
     }
-  return 0;
+
+  return retval;
 }
 
 // Eat whitespace and comments from FFILE, returning the text of the
@@ -782,7 +781,7 @@
 static void
 restore_command_history (void *)
 {
-  octave_command_history.ignore_entries (! Vsaving_history);
+  command_history::ignore_entries (! Vsaving_history);
 }
 
 static void
@@ -792,6 +791,12 @@
     fclose (static_cast<FILE *> (f));
 }
 
+static void
+restore_input_stream (void *f)
+{
+  command_editor::set_input_stream (static_cast<FILE *> (f));
+}
+
 static int
 parse_fcn_file (bool exec_script, const string& ff)
 {
@@ -803,15 +808,18 @@
 
   int old_reading_fcn_file_state = reading_fcn_file;
 
-  unwind_protect_ptr (rl_instream);
+  FILE *in_stream = command_editor::get_input_stream ();
+
+  add_unwind_protect (restore_input_stream, in_stream);
+
   unwind_protect_ptr (ff_instream);
 
-  unwind_protect_int (using_readline);
+  unwind_protect_int (line_editing);
   unwind_protect_int (input_line_number);
   unwind_protect_int (current_input_column);
   unwind_protect_int (reading_fcn_file);
 
-  using_readline = 0;
+  line_editing = 0;
   reading_fcn_file = 1;
   input_line_number = 0;
   current_input_column = 1;
@@ -828,9 +836,9 @@
       if (is_function_file (ffile))
 	{
 	  // XXX FIXME XXX -- we shouldn't need both the
-	  // octave_command_history object and the
+	  // command_history object and the
 	  // Vsaving_history variable...
-	  octave_command_history.ignore_entries ();
+	  command_history::ignore_entries ();
 
 	  add_unwind_protect (restore_command_history, 0);
 
@@ -877,9 +885,9 @@
 	  reading_fcn_file = old_reading_fcn_file_state;
 
 	  // XXX FIXME XXX -- we shouldn't need both the
-	  // octave_command_history object and the
+	  // command_history object and the
 	  // Vsaving_history variable...
-	  octave_command_history.ignore_entries ();
+	  command_history::ignore_entries ();
 
 	  add_unwind_protect (restore_command_history, 0);
 
@@ -1728,7 +1736,7 @@
       if (ival >= 0 && ival == val)
 	{
 	  Vhistory_size = ival;
-	  octave_command_history.set_size (ival);
+	  command_history::set_size (ival);
 	  return 0;
 	}
     }
@@ -1751,7 +1759,7 @@
   else
     {
       Vhistory_file = s;
-      octave_command_history.set_file (oct_tilde_expand (s));
+      command_history::set_file (file_ops::tilde_expand (s));
     }
 
   return status;
@@ -1782,7 +1790,7 @@
 {
   Vsaving_history = check_preference ("saving_history");
 
-  octave_command_history.ignore_entries (! Vsaving_history);
+  command_history::ignore_entries (! Vsaving_history);
 
   return 0;
 }
@@ -1822,11 +1830,12 @@
     "don't check to see if function files have changed since they were\n\
   last compiled.  Possible values are \"system\" and \"all\"");
 
-  DEFCONST (program_invocation_name, Vprogram_invocation_name, 0, 0,
+  DEFCONST (program_invocation_name,
+	    octave_env::get_program_invocation_name (), 0, 0,
     "the full name of the current program or script, including the\n\
 directory specification");
 
-  DEFCONST (program_name, Vprogram_name, 0, 0,
+  DEFCONST (program_name, octave_env::get_program_name (), 0, 0,
     "the name of the current program or script");
 
   DEFVAR (saving_history, 1.0, 0, saving_history,