changeset 2475:1d7925d6bede

[project @ 1996-11-07 04:36:00 by jwe]
author jwe
date Thu, 07 Nov 1996 04:46:54 +0000
parents b8c53143581b
children 4de4cebed088
files ChangeLog NEWS PROJECTS configure.in doc/interpreter/system.texi liboctave/Makefile.in liboctave/oct-alloc.cc liboctave/oct-alloc.h src/ChangeLog src/Makefile.in src/getgrent.cc src/getpwent.cc src/ov-struct.cc src/ov.cc src/ov.h src/pager.cc src/pt-const.cc src/pt-const.h src/sighandlers.cc src/syscalls.cc src/toplev.cc
diffstat 21 files changed, 720 insertions(+), 162 deletions(-) [+]
line wrap: on
line diff
--- a/ChangeLog	Wed Nov 06 19:16:08 1996 +0000
+++ b/ChangeLog	Thu Nov 07 04:46:54 1996 +0000
@@ -1,3 +1,7 @@
+Wed Nov  6 16:26:39 1996  John W. Eaton  <jwe@bevo.che.wisc.edu>
+
+	* configure.in: Add checks for group stuff.
+
 Tue Nov  5 12:32:30 1996  John W. Eaton  <jwe@bevo.che.wisc.edu>
 
 	* configure.in: Add checks for geteuid, getuid.
--- a/NEWS	Wed Nov 06 19:16:08 1996 +0000
+++ b/NEWS	Thu Nov 07 04:46:54 1996 +0000
@@ -306,8 +306,10 @@
       getpgrp  -- return the process group id of the current process
       getpid   -- return the process id of the current process
       getppid  -- return the process id of the parent process
-      geteuid  -- return the effective uid of the current process
-      getuid   -- return the uid of the current process
+      getuid   -- return the real user id of the current process
+      getgid   -- return the real group id of the current process
+      geteuid  -- return the effective user id of the current process
+      getegid  -- return the effective group id of the current process
       pipe     -- create an interprocess channel
 
   * Other new functions:
--- a/PROJECTS	Wed Nov 06 19:16:08 1996 +0000
+++ b/PROJECTS	Thu Nov 07 04:46:54 1996 +0000
@@ -509,6 +509,18 @@
   * It is likely that there are still some memory leaks.  Hunt then down
     and plug them. 
 
+  * Better error messages for missing operators?
+
+  * Eliminate duplicate enums in pt-exp.cc, pt-const.cc, and ov.cc.
+
+  * Handle octave_print_internal() stuff at the liboctave level.  Then
+    the octave_value classes could just call on the print() methods
+    for the underlying classes.
+
+  * As much as possible, eliminate explicit checks for the types of
+    octave_value objects so that user-defined types will automatically
+    do the right thing in more cases.
+
   * Only include config.h in files that actually need it, instead of
     including it in every .cc file.  Unfortunately, this might not be
     so easy to figure out.
--- a/configure.in	Wed Nov 06 19:16:08 1996 +0000
+++ b/configure.in	Thu Nov 07 04:46:54 1996 +0000
@@ -20,7 +20,7 @@
 ### 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.
 
-AC_REVISION($Revision: 1.227 $)
+AC_REVISION($Revision: 1.228 $)
 AC_PREREQ(2.9)
 AC_INIT(src/octave.cc)
 AC_CONFIG_HEADER(config.h)
@@ -654,10 +654,10 @@
 AC_HEADER_SYS_WAIT
 
 AC_CHECK_HEADERS(assert.h curses.h fcntl.h float.h floatingpoint.h \
-		 limits.h memory.h pwd.h sgtty.h stdlib.h string.h \
-		 sys/param.h sys/resource.h sys/select.h sys/stat.h \
-		 sys/time.h sys/times.h sys/types.h sys/utsname.h \
-		 termcap.h termio.h termios.h unistd.h varargs.h) 
+  grp.h limits.h memory.h pwd.h sgtty.h stdlib.h string.h sys/param.h \
+  sys/resource.h sys/select.h sys/stat.h sys/time.h sys/times.h \
+  sys/types.h sys/utsname.h termcap.h termio.h termios.h unistd.h \
+  varargs.h)
 
 if test "$ac_cv_header_termios_h" = yes \
     || test "$ac_cv_header_termio_h" = yes \
@@ -695,14 +695,13 @@
 
 ### Checks for functions and variables.
 
-AC_CHECK_FUNCS(atexit bcopy bzero dup2 endpwent execvp fcntl fork \
-	       getcwd geteuid gethostname getpgrp getpid getppid \
-	       getpwent getpwnam getpwuid getuid lstat memmove mkdir \
-	       mkfifo on_exit pipe putenv rename rindex rmdir \
-	       setpwent setvbuf sigaction sigpending sigprocmask \
-	       sigsuspend stat strcasecmp strdup strerror stricmp \
-	       strncasecmp strnicmp tempnam umask unlink vfprintf \
-	       vsprintf waitpid)
+AC_CHECK_FUNCS(atexit bcopy bzero dup2 endgrent endpwent execvp fcntl \
+  fork getcwd getegid geteuid getgid getgrent getgrgid getgrnam \
+  gethostname getpgrp getpid getppid getpwent getpwnam getpwuid getuid \
+  lstat memmove mkdir mkfifo on_exit pipe putenv rename rindex rmdir \
+  setgrent setpwent setvbuf sigaction sigpending sigprocmask \
+  sigsuspend stat strcasecmp strdup strerror stricmp strncasecmp \
+  strnicmp tempnam umask unlink vfprintf vsprintf waitpid)
 
 OCTAVE_SMART_PUTENV
 OCTAVE_PROGRAM_INVOCATION_NAME
@@ -1069,18 +1068,18 @@
 ### Do the substitutions in all the Makefiles.
 
 AC_OUTPUT(Makefile octMakefile Makeconf test/Makefile dlfcn/Makefile
-	  doc/Makefile doc/faq/Makefile doc/interpreter/Makefile
-	  doc/liboctave/Makefile doc/refcard/Makefile examples/Makefile
-	  liboctave/Makefile src/Makefile src/mk-oct-links
-	  libcruft/Makefile libcruft/Makerules libcruft/blas/Makefile
-	  libcruft/balgen/Makefile libcruft/dassl/Makefile
-	  libcruft/eispack/Makefile libcruft/fftpack/Makefile
-	  libcruft/fsqp/Makefile libcruft/lapack/Makefile
-	  libcruft/linpack/Makefile libcruft/minpack/Makefile
-	  libcruft/misc/Makefile libcruft/npsol/Makefile
-	  libcruft/odepack/Makefile libcruft/qpsol/Makefile
-	  libcruft/quadpack/Makefile libcruft/ranlib/Makefile
-	  libcruft/slatec-fn/Makefile libcruft/villad/Makefile)
+  doc/Makefile doc/faq/Makefile doc/interpreter/Makefile
+  doc/liboctave/Makefile doc/refcard/Makefile examples/Makefile
+  liboctave/Makefile src/Makefile src/mk-oct-links libcruft/Makefile
+  libcruft/Makerules libcruft/blas/Makefile libcruft/balgen/Makefile
+  libcruft/dassl/Makefile libcruft/eispack/Makefile
+  libcruft/fftpack/Makefile libcruft/fsqp/Makefile
+  libcruft/lapack/Makefile libcruft/linpack/Makefile
+  libcruft/minpack/Makefile libcruft/misc/Makefile
+  libcruft/npsol/Makefile libcruft/odepack/Makefile
+  libcruft/qpsol/Makefile libcruft/quadpack/Makefile
+  libcruft/ranlib/Makefile libcruft/slatec-fn/Makefile
+  libcruft/villad/Makefile)
 
 ### Print a summary so that important information isn't missed.
 
--- a/doc/interpreter/system.texi	Wed Nov 06 19:16:08 1996 +0000
+++ b/doc/interpreter/system.texi	Thu Nov 07 04:46:54 1996 +0000
@@ -16,6 +16,7 @@
 * Filesystem Utilities::        
 * Interacting with the OS::     
 * Password Database Functions::  
+* Group Database Functions::    
 * System Information::          
 * Other Functions::             
 @end menu
@@ -402,6 +403,22 @@
 Return the process id of the parent process.
 @end deftypefn
 
+@deftypefn {Built-in Function} {} geteuid ()
+Return the effective user id of the current process.
+@end deftypefn
+
+@deftypefn {Built-in Function} {} getuid ()
+Return the real user id of the current process.
+@end deftypefn
+
+@deftypefn {Built-in Function} {} getegid ()
+Return the effective group id of the current process.
+@end deftypefn
+
+@deftypefn {Built-in Function} {} getgid ()
+Return the real group id of the current process.
+@end deftypefn
+
 @deftypefn {Built-in Function} {} mkfifo       
 Create a FIFO special file.
 @end deftypefn
@@ -531,7 +548,7 @@
 from system to system.
 @end deffn
 
-@node Password Database Functions, System Information, Interacting with the OS, System Utilities
+@node Password Database Functions, Group Database Functions, Interacting with the OS, System Utilities
 @section Password Database Functions
 
 Octave's password database functions return information in a structure
@@ -585,7 +602,52 @@
 Close the password database.
 @end deftypefn
 
-@node System Information, Other Functions, Password Database Functions, System Utilities
+@node Group Database Functions, System Information, Password Database Functions, System Utilities
+@section Group Database Functions
+
+Octave's group database functions return information in a structure
+with the following fields.
+
+@table @code
+@item name
+The user name.
+
+@item passwd
+The encrypted password, if available.
+
+@item gid
+The numeric group id.
+
+@item mem
+The members of the group.
+@end table
+
+@deftypefn {Loadable Function} {group_struct =} getgrent ()
+Return an entry from the group database, opening it if necessary.
+Once the end of the data has been reached, @code{getgrent} returns 0.
+@end deftypefn
+
+@deftypefn {Loadable Function} {group_struct =} getgrgid (@var{gid}).
+Return the first entry from the group database with the group ID
+@var{gid}.  If the group ID does not exist in the database,
+@code{getgrgid} returns 0.
+@end deftypefn
+
+@deftypefn {Loadable Function} {group_struct =} getgrnam (@var{name})
+Return the first entry from the group database with the group name
+@var{name}.  If the group name does not exist in the database,
+@code{getgrname} returns 0.
+@end deftypefn
+
+@deftypefn {Loadable Function} {} setgrent ()
+Return the internal pointer to the beginning of the group database.
+@end deftypefn
+
+@deftypefn {Loadable Function} {} endgrent ()
+Close the group database.
+@end deftypefn
+
+@node System Information, Other Functions, Group Database Functions, System Utilities
 @section System Information
 
 @deftypefn {Built-in Function} {} computer ()
--- a/liboctave/Makefile.in	Wed Nov 06 19:16:08 1996 +0000
+++ b/liboctave/Makefile.in	Thu Nov 07 04:46:54 1996 +0000
@@ -39,8 +39,8 @@
 	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 f77-fcn.h getopt.h idx-vector.h lo-error.h \
-	lo-ieee.h lo-mappers.h lo-utils.h mach-info.h oct-cmplx.h \
-	oct-glob.h oct-math.h oct-term.h pathsearch.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 \
 	$(MATRIX_INC)
 
@@ -65,8 +65,9 @@
 	data-conv.cc dir-ops.cc erf.c erfc.c f77-fcn.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-glob.cc oct-term.cc pathsearch.cc prog-args.cc rename.c \
-	rmdir.c str-vec.cc sun-utils.cc tempname.c tempnam.c \
+	oct-alloc.cc oct-glob.cc oct-term.cc pathsearch.cc \
+	prog-args.cc rename.c rmdir.c str-vec.cc sun-utils.cc \
+	tempname.c tempnam.c \
 	$(TEMPLATE_SRC) \
 	$(TI_SRC) \
 	$(MATRIX_SRC)
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/liboctave/oct-alloc.cc	Thu Nov 07 04:46:54 1996 +0000
@@ -0,0 +1,110 @@
+/*
+
+Copyright (C) 1996 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 (__GNUG__)
+#pragma implementation
+#endif
+
+#ifdef HAVE_CONFIG_H
+#include <config.h>
+#endif
+
+#include <new>
+
+#include "oct-alloc.h"
+
+void *
+octave_allocator::alloc (size_t size)
+{
+  if (size != item_size)
+    return ::new char [size];
+
+  if (! head)
+    {
+      if (! grow ())
+	return 0;
+    }
+
+  link *tmp = head;
+  head = head->next;
+  return tmp;
+}
+
+void
+octave_allocator::free (void *p, size_t size)
+{
+  if (size != item_size)
+    ::delete [] ((char *) p);
+  else
+    {
+      link *tmp = (link *) p;
+      tmp->next = head;
+      head = tmp;
+    }
+}
+
+// Return TRUE for successful allocation, FALSE otherwise.
+
+bool
+octave_allocator::grow (void)
+{
+  bool retval = true;
+
+  char *start = new char [grow_size * item_size];
+
+  if (start)
+    {
+      char *last = &start[(grow_size - 1) * item_size];
+
+      char *p = start;
+      while (p < last)
+	{
+	  char *next = p + item_size;
+	  ((link *) p) -> next = (link *) next;
+	  p = next;
+	}
+
+      ((link *) last) -> next = 0;
+
+      head = (link *) start;
+    }
+  else
+    {
+      typedef void (*error_handler_function) (void);
+
+      error_handler_function f = set_new_handler (0);
+      set_new_handler (f);
+
+      if (f)
+	f ();
+
+      retval = false;
+    }
+
+  return retval;
+}
+
+/*
+;;; Local Variables: ***
+;;; mode: C++ ***
+;;; End: ***
+*/
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/liboctave/oct-alloc.h	Thu Nov 07 04:46:54 1996 +0000
@@ -0,0 +1,68 @@
+/*
+
+Copyright (C) 1996 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_oct_alloc_h)
+#define octave_oct_alloc_h 1
+
+class
+octave_allocator
+{
+public:
+
+  octave_allocator (size_t item_sz, int grow_sz = 256)
+    : head (0), grow_size (grow_sz),
+      item_size (item_sz > sizeof (link *) ? item_sz : sizeof (link *))
+  { }
+
+  // Get an object from the free list, possibly increasing the size of
+  // the free list.
+  void *alloc (size_t size);
+
+  // Put objects back on the free list.
+  void free (void *p, size_t size);
+
+private:
+
+  // Structure for internal free list management.
+  struct link { link *next; };
+
+  // Front of the free list.
+  link *head;
+
+  // How many objects to get each time we call the global operator new.
+  int grow_size;
+
+  // The size of each item on the list (or, if that is smaller than
+  // the size of list*, the size of list*.
+  size_t item_size;
+
+  // How to grow the free list.
+  bool grow (void);
+};
+
+#endif
+
+/*
+;;; Local Variables: ***
+;;; mode: C++ ***
+;;; End: ***
+*/
--- a/src/ChangeLog	Wed Nov 06 19:16:08 1996 +0000
+++ b/src/ChangeLog	Thu Nov 07 04:46:54 1996 +0000
@@ -1,5 +1,27 @@
 Wed Nov  6 12:32:48 1996  John W. Eaton  <jwe@bevo.che.wisc.edu>
 
+	* pt-const.h (tree_constant::allocator) New static member.
+	(tree_constant::operator new, tree_constant::operator delete):
+	Implement with custom allocator.
+
+	* syscalls.cc (Fgetgid, Fgetegid): New functions.
+
+	* sighandlers.cc (sigchld_handler): If necessary, reinstall
+	handler after call to waitpid().
+
+	* pager.cc (pager_death_handler): Don't use warning() to print
+	message.
+
+	* getgrent.cc: New file.
+	* Makefile.in (DLD_SRC): Add it.
+
+	* ov.cc (octave_value::print_with_name): Call is_map() instead of
+	print_as_structure().
+	* ov-struct.cc (octave_struct::print): Likewise.
+
+	* ov.h, ov.cc, pt-const.h: Delete force_numeric(), make_numeric(),
+	convert_to_matrix_type(), print_as_structure() member functions.
+
 	* variables.cc (is_function_file): Call gobble_leading_whitespace
 	here to strip all leading whitespace and comments.
 	(parse_fcn_file): If reading a function file, call
--- a/src/Makefile.in	Wed Nov 06 19:16:08 1996 +0000
+++ b/src/Makefile.in	Thu Nov 07 04:46:54 1996 +0000
@@ -62,8 +62,8 @@
 
 DLD_SRC := balance.cc chol.cc colloc.cc dassl.cc det.cc eig.cc \
 	   expm.cc fft.cc fft2.cc filter.cc find.cc fsolve.cc \
-	   fsqp.cc getpwent.cc getrusage.cc givens.cc hess.cc \
-	   ifft.cc ifft2.cc inv.cc log.cc lpsolve.cc lsode.cc \
+	   fsqp.cc getgrent.cc getpwent.cc getrusage.cc givens.cc \
+	   hess.cc ifft.cc ifft2.cc inv.cc log.cc lpsolve.cc lsode.cc \
 	   lu.cc minmax.cc npsol.cc pinv.cc qpsol.cc qr.cc quad.cc \
 	   qzval.cc rand.cc schur.cc sort.cc svd.cc syl.cc time.cc 
 
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/src/getgrent.cc	Thu Nov 07 04:46:54 1996 +0000
@@ -0,0 +1,230 @@
+/*
+
+Copyright (C) 1996 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 <string>
+
+#ifdef HAVE_SYS_TYPES_H
+#include <sys/types.h>
+#endif
+
+#ifdef HAVE_GRP_H
+#include <grp.h>
+#endif
+
+#include "defun-dld.h"
+#include "error.h"
+#include "gripes.h"
+#include "help.h"
+#include "oct-map.h"
+#include "ov.h"
+#include "oct-obj.h"
+#include "utils.h"
+
+// Group file functions.  (Why not?)
+
+static octave_value
+mk_gr_map (struct group *gr)
+{
+  octave_value retval;
+
+  if (gr)
+    {
+      Octave_map m;
+
+      m ["name"] = gr->gr_name;
+      m ["passwd"] = gr->gr_passwd;
+      m ["gid"] = STATIC_CAST (double, gr->gr_gid);
+
+      if (gr->gr_mem)
+	{
+	  // XXX FIXME XXX -- maybe there should be a string_vector
+	  // constructor that takes a NULL terminated list of C
+	  // strings.
+
+	  char **tmp = gr->gr_mem;
+
+	  int k = 0;
+	  while (*tmp++)
+	    k++;
+
+	  if (k > 0)
+	    {
+	      tmp = gr->gr_mem;
+
+	      string_vector members (k);
+
+	      for (int i = 0; i < k; i++)
+		members[i] = tmp[i];
+
+	      m ["mem"] = members;
+	    }
+	  else
+	    m ["mem"] = "";
+	}
+
+      retval = m;
+    }
+  else
+    retval = 0.0;
+
+  return retval;
+}
+
+DEFUN_DLD (getgrent, args, ,
+ "getgrent ()\n\
+\n\
+Read an entry from the group-file stream, opening it if necessary.")
+{
+  octave_value retval;
+
+  int nargin = args.length ();
+
+  if (nargin == 0)
+    {
+#ifdef HAVE_GETGRENT
+      retval = mk_gr_map (getgrent ());
+#else
+      gripe_not_supported ("getgrent");
+#endif
+    }
+  else
+    print_usage ("getgrent");
+
+  return retval;
+}
+
+DEFUN_DLD (getgrgid, args, ,
+  "getgrgid (GID)\n\
+\n\
+Search for a group entry with a matching group ID.")
+{
+  octave_value retval;
+
+  int nargin = args.length ();
+
+  if (nargin == 1)
+    {
+#ifdef HAVE_GETGRGID
+      double dval = args(0).double_value ();
+
+      if (! error_state)
+	{
+	  if (D_NINT (dval) == dval)
+	    {
+	      gid_t gid = STATIC_CAST (gid_t, dval);
+
+	      retval = mk_gr_map (getgrgid (gid));
+	    }
+	  else
+	    error ("getgrgid: argument must be an integer");
+	}
+#else
+      gripe_not_supported ("getgrgid");
+#endif
+    }
+  else
+    print_usage ("getgrgid");
+
+  return retval;
+}
+
+DEFUN_DLD (getgrnam, args, ,
+  "getgrnam (NAME)\n\
+\n\
+Search for group entry with a matching group name.")
+{
+  octave_value retval;
+
+  int nargin = args.length ();
+
+  if (nargin == 1)
+    {
+#ifdef HAVE_GETGRNAM
+      string s = args(0).string_value ();
+
+      if (! error_state)
+	retval = mk_gr_map (getgrnam (s.c_str ()));
+#else
+      gripe_not_supported ("getgrnam");
+#endif
+    }
+  else
+    print_usage ("getgrnam");
+
+  return retval;
+}
+
+DEFUN_DLD (setgrent, args, ,
+  "setgrent ()\n\
+\n\
+Rewind the group-file stream.")
+{
+  octave_value retval;
+
+  int nargin = args.length ();
+
+  if (nargin == 0)
+    {
+#ifdef HAVE_SETGRENT
+      setgrent ();
+#else
+      gripe_not_supported ("setgrent");
+#endif
+    }
+  else
+    print_usage ("setgrent");
+
+  return retval;
+}
+
+DEFUN_DLD (endgrent, args, ,
+  "endgrent ()\n\
+\n\
+Close the group-file stream.")
+{
+  octave_value retval;
+
+  int nargin = args.length ();
+
+  if (nargin == 0)
+    {
+#ifdef HAVE_ENDGRENT
+      endgrent ();
+#else
+      gripe_not_supported ("endgrent");
+#endif
+    }
+  else
+    print_usage ("endgrent");
+
+  return retval;
+}
+
+/*
+;;; Local Variables: ***
+;;; mode: C++ ***
+;;; End: ***
+*/
--- a/src/getpwent.cc	Wed Nov 06 19:16:08 1996 +0000
+++ b/src/getpwent.cc	Thu Nov 07 04:46:54 1996 +0000
@@ -77,16 +77,18 @@
 {
   octave_value retval;
 
-#ifdef HAVE_GETPWENT
   int nargin = args.length ();
 
   if (nargin == 0)
-    retval = mk_pw_map (getpwent ());
+    {
+#ifdef HAVE_GETPWENT
+      retval = mk_pw_map (getpwent ());
+#else
+      gripe_not_supported ("getpwent");
+#endif
+    }
   else
     print_usage ("getpwent");
-#else
-  gripe_not_supported ("getpwent");
-#endif
 
   return retval;
 }
@@ -98,11 +100,11 @@
 {
   octave_value retval;
 
-#ifdef HAVE_GETPWUID
   int nargin = args.length ();
 
   if (nargin == 1)
     {
+#ifdef HAVE_GETPWUID
       double dval = args(0).double_value ();
 
       if (! error_state)
@@ -116,12 +118,12 @@
 	  else
 	    error ("getpwuid: argument must be an integer");
 	}
+#else
+      gripe_not_supported ("getpwuid");
+#endif
     }
   else
     print_usage ("getpwuid");
-#else
-  gripe_not_supported ("getpwuid");
-#endif
 
   return retval;
 }
@@ -133,21 +135,21 @@
 {
   octave_value retval;
 
-#ifdef HAVE_GETPWNAM
   int nargin = args.length ();
 
   if (nargin == 1)
     {
+#ifdef HAVE_GETPWNAM
       string s = args(0).string_value ();
 
       if (! error_state)
 	retval = mk_pw_map (getpwnam (s.c_str ()));
+#else
+      gripe_not_supported ("getpwnam");
+#endif
     }
   else
     print_usage ("getpwnam");
-#else
-  gripe_not_supported ("getpwnam");
-#endif
 
   return retval;
 }
@@ -159,16 +161,18 @@
 {
   octave_value retval;
 
-#ifdef HAVE_SETPWENT
   int nargin = args.length ();
 
   if (nargin == 0)
-    setpwent ();
+    {
+#ifdef HAVE_SETPWENT
+      setpwent ();
+#else
+      gripe_not_supported ("setpwent");
+#endif
+    }
   else
     print_usage ("setpwent");
-#else
-  gripe_not_supported ("setpwent");
-#endif
 
   return retval;
 }
@@ -180,16 +184,18 @@
 {
   octave_value retval;
 
-#ifdef HAVE_ENDPWENT
   int nargin = args.length ();
 
   if (nargin == 0)
-    endpwent ();
+    {
+#ifdef HAVE_ENDPWENT
+      endpwent ();
+#else
+      gripe_not_supported ("endpwent");
+#endif
+    }
   else
     print_usage ("endpwent");
-#else
-  gripe_not_supported ("endpwent");
-#endif
 
   return retval;
 }
--- a/src/ov-struct.cc	Wed Nov 06 19:16:08 1996 +0000
+++ b/src/ov-struct.cc	Thu Nov 07 04:46:54 1996 +0000
@@ -93,7 +93,7 @@
 
 	  if (val.print_as_scalar ())
 	    os << " ";
-	  else if (val.print_as_structure ())
+	  else if (val.is_map ())
 	    {
 	      if (p)
 		pad_after = true;
--- a/src/ov.cc	Wed Nov 06 19:16:08 1996 +0000
+++ b/src/ov.cc	Thu Nov 07 04:46:54 1996 +0000
@@ -516,7 +516,7 @@
     {
       if (print_as_scalar ())
 	output_buf << name << " = ";
-      else if (print_as_structure ())
+      else if (is_map ())
 	{
 	  pad_after = true;
 	  output_buf << name << " =";
--- a/src/ov.h	Wed Nov 06 19:16:08 1996 +0000
+++ b/src/ov.h	Thu Nov 07 04:46:54 1996 +0000
@@ -377,31 +377,15 @@
 
   virtual string type_name (void) const { return rep->type_name (); }
 
-  virtual void convert_to_matrix_type (bool make_complex)
-    { rep->convert_to_matrix_type (make_complex); }
-
-  // Can we make these go away?
-
-  // These need better names, since a range really is a numeric type.
-
-  virtual void force_numeric (bool frc_str_conv = false)
-    { rep->force_numeric (frc_str_conv); }
-
-  octave_value make_numeric (bool) const
-    {
-      warning ("octave_value::make_numeric() is a no-op");
-      return *this;
-    }
-
-  bool print_as_scalar (void);
-
-  bool print_as_structure (void) { return is_map (); }
-
   // Binary and unary operations.
 
   friend octave_value do_binary_op (octave_value& a, octave_value& b,
 				    tree_expression::type t);
 
+  // Can we make these go away?
+
+  bool print_as_scalar (void);
+
 protected:
 
   octave_value (const octave_xvalue&) : rep (0) { }
--- a/src/pager.cc	Wed Nov 06 19:16:08 1996 +0000
+++ b/src/pager.cc	Thu Nov 07 04:46:54 1996 +0000
@@ -102,13 +102,22 @@
     {
       if (WIFEXITED (status) || WIFSIGNALLED (status))
 	{
-	  octave_pager_pid = -1;
+	  if (external_pager)
+	    clear_external_pager ();
 
 	  // Don't call error() here because we don't want to set
 	  // the error state.
 
-	  warning ("connection to external pager lost --");
-	  warning ("pending computations and output have been discarded");
+	  // XXX FIXME XXX -- something is wrong with the way that
+	  // we are cleaning up the pager in the event of a SIGCHLD.
+	  // If this message is printed with warning(), we eventually
+	  // crash.
+
+	  cout
+	    << "warning: connection to external pager (pid = "
+	    << pid << ") lost --" << endl
+	    << "warning: pending computations and output have been discarded"
+	    << endl;
 	}
     }
 }
@@ -209,11 +218,11 @@
 			       && ! Vpage_output_immediately
 			       && ! more_than_a_screenful (buf)));
 
+      seekoff (0, ios::beg);
+
       do_sync (buf, bypass_pager);
 
       octave_diary << buf;
-
-      seekoff (0, ios::beg);
     }
 
   return 0;
--- a/src/pt-const.cc	Wed Nov 06 19:16:08 1996 +0000
+++ b/src/pt-const.cc	Thu Nov 07 04:46:54 1996 +0000
@@ -60,6 +60,10 @@
 #include "utils.h"
 #include "variables.h"
 
+// We are likely to have a lot of tree_constants to allocate, so make
+// the grow_size large.
+octave_allocator tree_constant::allocator (sizeof (tree_constant), 1024);
+
 Octave_map
 tree_constant::map_value (void) const
 {
--- a/src/pt-const.h	Wed Nov 06 19:16:08 1996 +0000
+++ b/src/pt-const.h	Thu Nov 07 04:46:54 1996 +0000
@@ -33,6 +33,7 @@
 
 #include "Range.h"
 #include "mx-base.h"
+#include "oct-alloc.h"
 #include "str-vec.h"
 
 #include "pt-fvc.h"
@@ -156,10 +157,11 @@
       return *this;
     }
 
-#if 0
-  void *operator new (size_t size);
-  void operator delete (void *p, size_t size);
-#endif
+  void *operator new (size_t size)
+    { return allocator.alloc (size); }
+
+  void operator delete (void *p, size_t size)
+    { allocator.free (p, size); }
 
   // Indexed assignment.
 
@@ -347,25 +349,14 @@
 
 private:
 
+  // For custom memory management.
+  static octave_allocator allocator;
+
+  // The actual value that this constant refers to.
   octave_value val;
 
+  // The original text form of this constant.
   string orig_text;
-
-  void convert_to_matrix_type (bool make_complex)
-    { val.convert_to_matrix_type (make_complex); }
-
-  // Can we make these go away?
-
-  // These need better names, since a range really is a numeric type.
-
-  void force_numeric (bool frc_str_conv = false)
-    { val.force_numeric (frc_str_conv); }
-
-  octave_value make_numeric (bool frc_str_conv = false) const;
-
-  bool print_as_scalar (void) { return val.print_as_scalar (); }
-
-  bool print_as_structure (void) { return val.print_as_structure (); }
 };
 
 #endif
--- a/src/sighandlers.cc	Wed Nov 06 19:16:08 1996 +0000
+++ b/src/sighandlers.cc	Thu Nov 07 04:46:54 1996 +0000
@@ -140,10 +140,6 @@
 static RETSIGTYPE
 sigchld_handler (int /* sig */)
 {
-#ifdef MUST_REINSTALL_SIGHANDLERS
-  octave_set_signal_handler (SIGCHLD, sigchld_handler);
-#endif
-
   int n = octave_child_list::length ();
 
   for (int i = 0; i < n; i++)
@@ -163,13 +159,17 @@
 	      octave_child::dead_child_handler f = elt.handler;
 
 	      if (f)
-		(*f) (pid, status);
+		f (pid, status);
 
 	      break;
 	    }
 	}
     }
 
+#ifdef MUST_REINSTALL_SIGHANDLERS
+  octave_set_signal_handler (SIGCHLD, sigchld_handler);
+#endif
+
   SIGHANDLER_RETURN (0);
 }
 
--- a/src/syscalls.cc	Wed Nov 06 19:16:08 1996 +0000
+++ b/src/syscalls.cc	Thu Nov 07 04:46:54 1996 +0000
@@ -90,11 +90,11 @@
 {
   double retval = -1.0;
 
-#if defined (HAVE_DUP2)
   int nargin = args.length ();
 
   if (nargin == 2)
     {
+#if defined (HAVE_DUP2)
       double d_old = args(0).double_value ();
       double d_new = args(1).double_value ();
 
@@ -114,12 +114,12 @@
 	  else
 	    error ("dup2: arguments must be integer values");
 	}
+#else
+      gripe_not_supported ("dup2");
+#endif
     }
   else
     print_usage ("dup2");
-#else
-  gripe_not_supported ("dup2");
-#endif
 
   return retval;
 }
@@ -129,11 +129,11 @@
 {
   double retval = -1.0;
 
-#if defined (HAVE_EXECVP)
   int nargin = args.length ();
 
   if (nargin == 1 || nargin == 2)
     {
+#if defined (HAVE_EXECVP)
       string exec_file = args(0).string_value ();
 
       if (! error_state)
@@ -182,12 +182,12 @@
 	}
       else
 	error ("exec: first argument must be a string");
+#else
+      gripe_not_supported ("exec");
+#endif
     }
   else
     print_usage ("exec");
-#else
-  gripe_not_supported ("exec");
-#endif
 
   return retval;
 }
@@ -197,11 +197,11 @@
 {
   double retval = -1.0;
 
-#if defined (HAVE_FCNTL)
   int nargin = args.length ();
 
   if (nargin == 3)
     {
+#if defined (HAVE_FCNTL)
       double d_fid = args(0).double_value ();
       double d_req = args(1).double_value ();
       double d_arg = args(2).double_value ();
@@ -223,12 +223,12 @@
 	}
       else
 	error ("fcntl: file id must be an integer");
+#else
+      gripe_not_supported ("fcntl");
+#endif
     }
   else
     print_usage ("fcntl");
-#else
-  gripe_not_supported ("fcntl");
-#endif
 
   return retval;
 }
@@ -238,16 +238,18 @@
 {
   double retval = -1.0;
 
-#if defined (HAVE_FORK)
   int nargin = args.length ();
 
   if (nargin == 0)
-    retval = fork ();
+    {
+#if defined (HAVE_FORK)
+      retval = fork ();
+#else
+      gripe_not_supported ("fork");
+#endif
+    }
   else
     print_usage ("fork");
-#else
-  gripe_not_supported ("fork");
-#endif
 
   return retval;
 }
@@ -257,16 +259,18 @@
 {
   double retval = -1.0;
 
-#if defined (HAVE_GETPGRP)
   int nargin = args.length ();
 
   if (nargin == 0)
-    retval = getpgrp ();
+    {
+#if defined (HAVE_GETPGRP)
+      retval = getpgrp ();
+#else
+      gripe_not_supported ("getpgrp");
+#endif
+    }
   else
     print_usage ("getpgrp");
-#else
-  gripe_not_supported ("getpgrp");
-#endif
 
   return retval;
 }
@@ -276,16 +280,18 @@
 {
   double retval = -1.0;
 
-#if defined (HAVE_GETPID)
   int nargin = args.length ();
 
   if (nargin == 0)
-    retval = getpid ();
+    {
+#if defined (HAVE_GETPID)
+      retval = getpid ();
+#else
+      gripe_not_supported ("getpid");
+#endif
+    }
   else
     print_usage ("getpid");
-#else
-  gripe_not_supported ("getpid");
-#endif
 
   return retval;
 }
@@ -295,16 +301,60 @@
 {
   double retval = -1.0;
 
+  int nargin = args.length ();
+
+  if (nargin == 0)
+    {
 #if defined (HAVE_GETPPID)
+      retval = getppid ();
+#else
+      gripe_not_supported ("getppid");
+#endif
+    }
+  else
+    print_usage ("getppid");
+
+  return retval;
+}
+
+DEFUN (getegid, args, ,
+  "gid = getegid (): return the effective group id of the current process")
+{
+  double retval = -1.0;
+
   int nargin = args.length ();
 
   if (nargin == 0)
-    retval = getppid ();
+    {
+#if defined (HAVE_GETEGID)
+      retval = getegid ();
+#else
+      gripe_not_supported ("getegid");
+#endif
+    }
   else
-    print_usage ("getppid");
+    print_usage ("getegid");
+
+  return retval;
+}
+
+DEFUN (getgid, args, ,
+  "gid = getgid (): return the real group id of the current process")
+{
+  double retval = -1.0;
+
+  int nargin = args.length ();
+
+  if (nargin == 0)
+    {
+#if defined (HAVE_GETGID)
+      retval = getgid ();
 #else
-  gripe_not_supported ("getppid");
+      gripe_not_supported ("getgid");
 #endif
+    }
+  else
+    print_usage ("getgid");
 
   return retval;
 }
@@ -314,16 +364,18 @@
 {
   double retval = -1.0;
 
-#if defined (HAVE_GETEUID)
   int nargin = args.length ();
 
   if (nargin == 0)
-    retval = geteuid ();
+    {
+#if defined (HAVE_GETEUID)
+      retval = geteuid ();
+#else
+      gripe_not_supported ("geteuid");
+#endif
+    }
   else
     print_usage ("geteuid");
-#else
-  gripe_not_supported ("geteuid");
-#endif
 
   return retval;
 }
@@ -333,16 +385,18 @@
 {
   double retval = -1.0;
 
-#if defined (HAVE_GETUID)
   int nargin = args.length ();
 
   if (nargin == 0)
-    retval = getuid ();
+    {
+#if defined (HAVE_GETUID)
+      retval = getuid ();
+#else
+      gripe_not_supported ("getuid");
+#endif
+    }
   else
     print_usage ("getuid");
-#else
-  gripe_not_supported ("getuid");
-#endif
 
   return retval;
 }
@@ -428,11 +482,11 @@
 {
   octave_value_list retval (2, octave_value (-1.0));
 
-#if defined (HAVE_PIPE)
   int nargin = args.length ();
 
   if (nargin == 0)
     {
+#if defined (HAVE_PIPE)
       int fid[2];
 
       if (pipe (fid) >= 0)
@@ -454,12 +508,12 @@
           retval(0) = file_ids;
 	  retval(1) = 0.0;
 	}	  
+#else
+      gripe_not_supported ("pipe");
+#endif
     }
   else
     print_usage ("pipe");
-#else
-  gripe_not_supported ("pipe");
-#endif
 
   return retval;
 }
@@ -580,11 +634,11 @@
 {
   double retval = -1.0;
 
-#if defined (HAVE_WAITPID)
   int nargin = args.length ();
 
   if (nargin == 1 || nargin == 2)
     {
+#if defined (HAVE_WAITPID)
       double pid_num = args(0).double_value ();
   
       if (! error_state)
@@ -618,12 +672,12 @@
 		retval = waitpid (pid, 0, options);
 	    }
 	}
+#else
+      gripe_not_supported ("waitpid");
+#endif
     }
   else
     print_usage ("waitpid");
-#else
-  gripe_not_supported ("waitpid");
-#endif
 
   return retval;
 }
--- a/src/toplev.cc	Wed Nov 06 19:16:08 1996 +0000
+++ b/src/toplev.cc	Thu Nov 07 04:46:54 1996 +0000
@@ -755,23 +755,23 @@
 {
   octave_value_list retval;
 
-#if defined (HAVE_ATEXIT) || defined (HAVE_ON_EXIT)
   int nargin = args.length ();
 
   if (nargin == 1)
     {
+#if defined (HAVE_ATEXIT) || defined (HAVE_ON_EXIT)
       string arg = args(0).string_value ();
 
       if (! error_state)
 	octave_atexit_functions.push (arg);
       else
 	error ("atexit: argument must be a string");
+#else
+      gripe_not_supported ("atexit");
+#endif
     }
   else
     print_usage ("atexit");
-#else
-  gripe_not_supported ("atexit");
-#endif
 
   return retval;
 }