changeset 4180:84fe3ca3a246

[project @ 2002-11-15 04:47:01 by jwe]
author jwe
date Fri, 15 Nov 2002 04:47:02 +0000
parents 8734ba917fea
children dd2abf428f5d
files ChangeLog configure.in libcruft/ChangeLog libcruft/misc/f77-fcn.h libcruft/misc/quit.cc libcruft/misc/quit.h liboctave/ChangeLog liboctave/DASPK.cc liboctave/DASRT.cc liboctave/DASSL.cc liboctave/LSODE.cc liboctave/NLEqn.cc liboctave/ODESSA.cc liboctave/Quad.cc liboctave/lo-specfun.cc src/ChangeLog src/sighandlers.cc src/toplev.cc
diffstat 18 files changed, 253 insertions(+), 55 deletions(-) [+]
line wrap: on
line diff
--- a/ChangeLog
+++ b/ChangeLog
@@ -1,3 +1,9 @@
+2002-11-14  John W. Eaton  <jwe@bevo.che.wisc.edu>
+
+	* configure.in: Check for sigsetjmp and siglongjmp.
+	(AH_BOTTOM): If both are found, define OCTAVE_HAVE_SIG_JUMP.
+	Also check for sig_atomic_t, typedef it if not available.
+
 2002-11-10  Per Persson <persquare@mac.com>
 
 	* configure.in: Detect dyld API for dynamic linking on OS X.
--- a/configure.in
+++ b/configure.in
@@ -22,7 +22,7 @@
 ### 02111-1307, USA. 
 
 AC_INIT
-AC_REVISION($Revision: 1.388 $)
+AC_REVISION($Revision: 1.389 $)
 AC_PREREQ(2.52)
 AC_CONFIG_SRCDIR([src/octave.cc])
 AC_CONFIG_HEADER(config.h)
@@ -898,10 +898,10 @@
   getgrnam getpgrp getpid getppid getpwent \
   getpwuid gettimeofday getuid getwd _kbhit kill link localtime_r lstat \
   memmove mkdir mkfifo on_exit pipe poll putenv raise readlink rename \
-  rindex rmdir select setgrent setpwent setvbuf sigaction sigpending \
-  sigprocmask sigsuspend stat strcasecmp strdup strerror strftime \
-  stricmp strncasecmp strnicmp strptime symlink tempnam umask unlink \
-  usleep vfprintf vsprintf vsnprintf waitpid)
+  rindex rmdir select setgrent setpwent setvbuf sigaction siglongjmp \
+  sigpending sigprocmask sigsuspend stat strcasecmp strdup \
+  strerror strftime stricmp strncasecmp strnicmp strptime symlink \
+  tempnam umask unlink usleep vfprintf vsprintf vsnprintf waitpid)
 
 OCTAVE_SMART_PUTENV
 
@@ -1134,7 +1134,7 @@
 AC_TYPE_SIZE_T
 AC_TYPE_UID_T
 AC_CHECK_TYPES([dev_t, ino_t, nlink_t, nlink_t])
-AC_CHECK_TYPES(sigset_t, , , [#include <signal.h>])
+AC_CHECK_TYPES([sigset_t, sig_atomic_t], , , [#include <signal.h>])
 
 ### A system dependent kluge or two.
 
@@ -1314,6 +1314,10 @@
 typedef int sigset_t;
 #endif
 
+#if !defined(HAVE_SIG_ATOMIC_T)
+typedef int sig_atomic_t;
+#endif
+
 #define OCTAVE_HAVE_POSIX_FILESYSTEM 1
 
 #if defined (__WIN32__)
@@ -1329,6 +1333,11 @@
 #endif
 
 #define USE_EXCEPTIONS_FOR_INTERRUPTS 1
+
+/* sigsetjmp is a macro, not a function. */
+#if defined (sigsetjmp) && defined (HAVE_SIGLONGJMP)
+#define OCTAVE_HAVE_SIG_JUMP
+#endif
 ])
 
 ### Do the substitutions in all the Makefiles.
--- a/libcruft/ChangeLog
+++ b/libcruft/ChangeLog
@@ -1,3 +1,25 @@
+2002-11-14  John W. Eaton  <jwe@bevo.che.wisc.edu>
+
+	* misc/quit.cc (octave_allocation_error): New variable.
+	(octave_throw_bad_alloc): New function.
+	* misc/quit.h: Provide decls.
+	(OCTAVE_THROW_BAD_ALLOC): New macro.
+	(END_INTERRUPT_WITH_EXCEPTIONS): Also catch bad_alloc.
+	* misc/f77-fcn.h (F77_XFCN): Handle allocation errors.
+
+	* misc/quit.h (octave_jmp_buf): New typedef.
+	(current_context): Type is now octave_jmp_buf.
+	(octave_set_current_context): Use sigsetjmp if we have it.
+	(octave_interrupt_immediately, octave_interrupt_state): Type is
+	now sig_atomic_t.
+	(BEGIN_INTERRUPT_WITH_EXCEPTIONS, END_INTERRUPT_WITH_EXCEPTIONS):
+	New macros.
+
+	* misc/quit.cc (octave_jump_to_enclosing_context): Use siglongjmp
+	if we have it.	
+	(octave_save_current_context, octave_restore_current_context): Use
+	octave_jmp_buf type here.
+
 2002-11-07  John W. Eaton  <jwe@bevo.che.wisc.edu>
 
 	* misc/Makefile.in: Handle automatic dependency generation for
--- a/libcruft/misc/f77-fcn.h
+++ b/libcruft/misc/f77-fcn.h
@@ -29,8 +29,6 @@
 
 #include "quit.h"
 
-#include <stdio.h>
-
 /* Hack to stringize macro results. */
 #define xSTRINGIZE(x) #x
 #define STRINGIZE(x) xSTRINGIZE(x)
@@ -61,6 +59,8 @@
           octave_restore_current_context ((char *) saved_context); \
 	  if (f77_exception_encountered) \
 	    F77_XFCN_ERROR (f, F); \
+          else if (octave_allocation_error) \
+            OCTAVE_THROW_BAD_ALLOC; \
           else \
             OCTAVE_THROW_TO_TOP_LEVEL; \
 	} \
--- a/libcruft/misc/quit.cc
+++ b/libcruft/misc/quit.cc
@@ -26,6 +26,8 @@
 
 #include <cstring>
 
+#include <new>
+
 // Include signal.h, not csignal since the latter might only define
 // the ANSI standard C signal interface.
 
@@ -33,24 +35,28 @@
 
 #include "quit.h"
 
-jmp_buf current_context;
+octave_jmp_buf current_context;
 
 void
 octave_save_current_context (void *save_buf)
 {
-  memcpy (save_buf, current_context, sizeof (jmp_buf));
+  memcpy (save_buf, current_context, sizeof (octave_jmp_buf));
 }
 
 void
 octave_restore_current_context (void *save_buf)
 {
-  memcpy (current_context, save_buf, sizeof (jmp_buf));
+  memcpy (current_context, save_buf, sizeof (octave_jmp_buf));
 }
 
 void
 octave_jump_to_enclosing_context (void)
 {
+#if defined (OCTAVE_HAVE_SIG_JUMP)
+  siglongjmp (current_context, 1);
+#else
   longjmp (current_context, 1);
+#endif
 }
 
 // Allow us to save the signal mask and then restore it to the most
@@ -83,9 +89,11 @@
 
 #if defined (USE_EXCEPTIONS_FOR_INTERRUPTS)
 
-int octave_interrupt_immediately = 0;
+sig_atomic_t octave_interrupt_immediately = 0;
 
-int octave_interrupt_state = 0;
+sig_atomic_t octave_interrupt_state = 0;
+
+sig_atomic_t octave_allocation_error = 0;
 
 void
 octave_throw_interrupt_exception (void)
@@ -93,6 +101,12 @@
   throw octave_interrupt_exception ();
 }
 
+void
+octave_throw_bad_alloc (void)
+{
+  throw bad_alloc ();
+}
+
 #endif
 
 /*
--- a/libcruft/misc/quit.h
+++ b/libcruft/misc/quit.h
@@ -27,17 +27,29 @@
 extern "C" {
 #endif
 
-// Include setjmp.h, not csetjmp since the latter might only define
-// the ANSI standard C interface.
+#include <stdio.h>
 
+#include <signal.h>
 #include <setjmp.h>
 
-extern jmp_buf current_context;
+#if defined (OCTAVE_HAVE_SIG_JUMP)
+
+typedef sigjmp_buf octave_jmp_buf;
+
+#define octave_set_current_context sigsetjmp (current_context, 1)
+
+#else
+
+typedef jmp_buf octave_jmp_buf;
+
+#define octave_set_current_context setjmp (current_context)
+
+#endif
+
+extern octave_jmp_buf current_context;
 
 extern void octave_save_current_context (void *);
 
-#define octave_set_current_context setjmp (current_context)
-
 extern void octave_restore_current_context (void *);
 
 extern void octave_jump_to_enclosing_context (void) GCC_ATTR_NORETURN;
@@ -55,12 +67,16 @@
 };
 #endif
 
-extern int octave_interrupt_immediately;
+extern sig_atomic_t octave_interrupt_immediately;
 
-extern int octave_interrupt_state;
+extern sig_atomic_t octave_interrupt_state;
+
+extern sig_atomic_t octave_allocation_error;
 
 extern void octave_throw_interrupt_exception (void) GCC_ATTR_NORETURN;
 
+extern void octave_throw_bad_alloc (void) GCC_ATTR_NORETURN;
+
 #define OCTAVE_QUIT \
   do \
     { \
@@ -77,10 +93,15 @@
 
 #define OCTAVE_THROW_TO_TOP_LEVEL octave_throw_interrupt_exception ()
 
+#define OCTAVE_THROW_BAD_ALLOC octave_throw_bad_alloc ()
+
 #define OCTAVE_TRY_WITH_INTERRUPTS try
 
 #define OCTAVE_CATCH_INTERRUPTS catch (octave_interrupt_exception)
 
+#define SAVE_OCTAVE_INTERRUPT_IMMEDIATELY(var) \
+  sig_atomic_t var = octave_interrupt_immediately
+
 #define INCREMENT_OCTAVE_INTERRUPT_IMMEDIATELY \
   do { octave_interrupt_immediately++; } while (0)
 
@@ -113,6 +134,29 @@
     } \
   while (0)
 
+#define BEGIN_INTERRUPT_WITH_EXCEPTIONS \
+  SAVE_OCTAVE_INTERRUPT_IMMEDIATELY (saved_octave_interrupt_immediately); \
+ \
+  OCTAVE_TRY_WITH_INTERRUPTS \
+    { \
+      SET_OCTAVE_INTERRUPT_IMMEDIATELY (0)
+
+#define END_INTERRUPT_WITH_EXCEPTIONS \
+    } \
+  OCTAVE_CATCH_INTERRUPTS \
+    { \
+      SET_OCTAVE_INTERRUPT_IMMEDIATELY (saved_octave_interrupt_immediately); \
+      octave_jump_to_enclosing_context (); \
+    } \
+  catch (bad_alloc) \
+    { \
+      SET_OCTAVE_INTERRUPT_IMMEDIATELY (saved_octave_interrupt_immediately); \
+      octave_allocation_error = 1; \
+      octave_jump_to_enclosing_context (); \
+    } \
+ \
+  SET_OCTAVE_INTERRUPT_IMMEDIATELY (saved_octave_interrupt_immediately)
+
 #else
 
 #define OCTAVE_QUIT do { } while (0)
@@ -121,10 +165,16 @@
 
 #define OCTAVE_THROW_TO_TOP_LEVEL OCTAVE_JUMP_TO_TOP_LEVEL
 
+#define OCTAVE_THROW_BAD_ALLOC OCTAVE_JUMP_TO_TOP_LEVEL
+
 #define OCTAVE_TRY_WITH_INTERRUPTS
 
 #define OCTAVE_CATCH_INTERRUPTS if (0)
 
+#define SAVE_OCTAVE_INTERRUPT_IMMEDIATELY(var) do { } while (0)
+
+#define SET_OCTAVE_INTERRUPT_IMMEDIATELY(x) do { } while (0)
+
 #define INCREMENT_OCTAVE_INTERRUPT_IMMEDIATELY do { } while (0)
 
 #define DECREMENT_OCTAVE_INTERRUPT_IMMEDIATELY do { } while (0)
@@ -133,6 +183,10 @@
 
 #define END_INTERRUPT_IMMEDIATELY_IN_FOREIGN_CODE do { } while (0)
 
+#define BEGIN_INTERRUPT_WITH_EXCEPTIONS do { } while (0)
+
+#define END_INTERRUPT_WITH_EXCEPTIONS do { } while (0)
+
 #endif
 
 #ifdef __cplusplus
--- a/liboctave/ChangeLog
+++ b/liboctave/ChangeLog
@@ -1,3 +1,18 @@
+2002-11-14  John W. Eaton  <jwe@bevo.che.wisc.edu>
+
+	* lo-specfun.cc: Use F77_FUNC instead of F77_XFCN for calls to
+	fortran code that should run fast enough that it is not worth all
+	the setup costs of F77_XFCN.
+
+	* Quad.cc (user_function): Surround body of function with
+	BEGIN_INTERRUPT_WITH_EXCEPTIONS, END_INTERRUPT_WITH_EXCEPTIONS.
+	* ODESSA.cc (odessa_f, odessa_j, odessa_b): Likewise.
+	* NLEqn.cc (hybrd1_fcn, hybrj1_fcn): Likewise.
+	* LSODE.cc (lsode_f, lsode_j): Likewise.
+	* DASSL.cc (ddassl_f, ddassl_j): Likewise.
+	* DASRT.cc (ddasrt_f, ddasrt_j, ddasrt_g): Likewise.
+	* DASPK.cc (ddaspk_f, ddaspk_psol, ddaspk_j): Likewise.
+
 2002-11-11  John W. Eaton  <jwe@bevo.che.wisc.edu>
 
 	* lo-ieee.cc (octave_ieee_init): Check defined (__osf__) instead
--- a/liboctave/DASPK.cc
+++ b/liboctave/DASPK.cc
@@ -68,6 +68,8 @@
 ddaspk_f (const double& time, const double *state, const double *deriv,
 	  const double&, double *delta, int& ires, double *, int *)
 {
+  BEGIN_INTERRUPT_WITH_EXCEPTIONS;
+
   ColumnVector tmp_deriv (nn);
   ColumnVector tmp_state (nn);
   ColumnVector tmp_delta (nn);
@@ -91,6 +93,8 @@
 	}
     }
 
+  END_INTERRUPT_WITH_EXCEPTIONS;
+
   return 0;
 }
 
@@ -104,7 +108,12 @@
 	     int *iwp, double *b, const double& eplin, int& ier,
 	     double *, int*)
 {
+  BEGIN_INTERRUPT_WITH_EXCEPTIONS;
+
   abort ();
+
+  END_INTERRUPT_WITH_EXCEPTIONS;
+
   return 0;
 }
 
@@ -113,6 +122,8 @@
 ddaspk_j (const double& time, const double *state, const double *deriv,
 	  double *pd, const double& cj, double *, int *)
 {
+  BEGIN_INTERRUPT_WITH_EXCEPTIONS;
+
   // XXX FIXME XXX -- would be nice to avoid copying the data.
 
   ColumnVector tmp_state (nn);
@@ -130,6 +141,8 @@
     for (int i = 0; i < nn; i++)
       pd [nn * j + i] = tmp_pd.elem (i, j);
 
+  END_INTERRUPT_WITH_EXCEPTIONS;
+
   return 0;
 }
 
--- a/liboctave/DASRT.cc
+++ b/liboctave/DASRT.cc
@@ -35,6 +35,7 @@
 #include "f77-fcn.h"
 #include "lo-error.h"
 #include "lo-sstream.h"
+#include "quit.h"
 
 typedef int (*dasrt_fcn_ptr) (const double&, const double*, const double*,
 			      double*, int&, double*, int*);
@@ -63,6 +64,8 @@
 ddasrt_f (const double& t, const double *state, const double *deriv,
 	  double *delta, int& ires, double *rpar, int *ipar)
 {
+  BEGIN_INTERRUPT_WITH_EXCEPTIONS;
+
   ColumnVector tmp_state (nn);
   ColumnVector tmp_deriv (nn);
 
@@ -82,6 +85,8 @@
 	delta[i] = tmp_fval(i);
     }
 
+  END_INTERRUPT_WITH_EXCEPTIONS;
+
   return 0;
 }
 
@@ -89,6 +94,8 @@
 ddasrt_j (const double& time, const double *state, const double *deriv,
 	  double *pd, const double& cj, double *, int *)
 {
+  BEGIN_INTERRUPT_WITH_EXCEPTIONS;
+
   // XXX FIXME XXX -- would be nice to avoid copying the data.
 
   ColumnVector tmp_state (nn);
@@ -106,6 +113,8 @@
     for (int i = 0; i < nn; i++)
       pd [nn * j + i] = tmp_pd.elem (i, j);
 
+  END_INTERRUPT_WITH_EXCEPTIONS;
+
   return 0;
 }
 
@@ -113,6 +122,8 @@
 ddasrt_g (const int& neq, const double& t, const double *state,
 	  const int& ng, double *gout, double *rpar, int *ipar) 
 {
+  BEGIN_INTERRUPT_WITH_EXCEPTIONS;
+
   int n = neq;
 
   ColumnVector tmp_state (n);
@@ -124,6 +135,8 @@
   for (int i = 0; i < ng; i++)
     gout[i] = tmp_fval(i);
 
+  END_INTERRUPT_WITH_EXCEPTIONS;
+
   return 0;
 }
 
--- a/liboctave/DASSL.cc
+++ b/liboctave/DASSL.cc
@@ -35,6 +35,7 @@
 #include "f77-fcn.h"
 #include "lo-error.h"
 #include "lo-sstream.h"
+#include "quit.h"
 
 typedef int (*dassl_fcn_ptr) (const double&, const double*, const double*,
 			      double*, int&, double*, int*);
@@ -59,6 +60,8 @@
 ddassl_f (const double& time, const double *state, const double *deriv,
 	  double *delta, int& ires, double *, int *)
 {
+  BEGIN_INTERRUPT_WITH_EXCEPTIONS;
+
   // XXX FIXME XXX -- would be nice to avoid copying the data.
 
   ColumnVector tmp_deriv (nn);
@@ -84,6 +87,8 @@
 	}
     }
 
+  END_INTERRUPT_WITH_EXCEPTIONS;
+
   return 0;
 }
 
@@ -91,6 +96,8 @@
 ddassl_j (const double& time, const double *state, const double *deriv,
 	  double *pd, const double& cj, double *, int *)
 {
+  BEGIN_INTERRUPT_WITH_EXCEPTIONS;
+
   // XXX FIXME XXX -- would be nice to avoid copying the data.
 
   ColumnVector tmp_state (nn);
@@ -108,6 +115,8 @@
     for (int i = 0; i < nn; i++)
       pd [nn * j + i] = tmp_pd.elem (i, j);
 
+  END_INTERRUPT_WITH_EXCEPTIONS;
+
   return 0;
 }
 
--- a/liboctave/LSODE.cc
+++ b/liboctave/LSODE.cc
@@ -35,6 +35,7 @@
 #include "f77-fcn.h"
 #include "lo-error.h"
 #include "lo-sstream.h"
+#include "quit.h"
 
 typedef int (*lsode_fcn_ptr) (const int&, const double&, double*,
 			      double*, int&);
@@ -57,6 +58,8 @@
 lsode_f (const int& neq, const double& time, double *,
 	 double *deriv, int& ierr) 
 {
+  BEGIN_INTERRUPT_WITH_EXCEPTIONS;
+
   ColumnVector tmp_deriv;
 
   // NOTE: this won't work if LSODE passes copies of the state vector.
@@ -73,6 +76,8 @@
 	deriv [i] = tmp_deriv.elem (i);
     }
 
+  END_INTERRUPT_WITH_EXCEPTIONS;
+
   return 0;
 }
 
@@ -80,6 +85,8 @@
 lsode_j (const int& neq, const double& time, double *,
 	 const int&, const int&, double *pd, const int& nrowpd)
 {
+  BEGIN_INTERRUPT_WITH_EXCEPTIONS;
+
   Matrix tmp_jac (neq, neq);
 
   // NOTE: this won't work if LSODE passes copies of the state vector.
@@ -92,6 +99,8 @@
     for (int i = 0; i < neq; i++)
       pd [nrowpd * j + i] = tmp_jac (i, j);
 
+  END_INTERRUPT_WITH_EXCEPTIONS;
+
   return 0;
 }
 
--- a/liboctave/NLEqn.cc
+++ b/liboctave/NLEqn.cc
@@ -32,6 +32,7 @@
 #include "dMatrix.h"
 #include "f77-fcn.h"
 #include "lo-error.h"
+#include "quit.h"
 
 typedef int (*hybrd1_fcn_ptr) (int*, double*, double*, int*);
 
@@ -63,6 +64,8 @@
 int
 hybrd1_fcn (int *n, double *x, double *fvec, int *iflag)
 {
+  BEGIN_INTERRUPT_WITH_EXCEPTIONS;
+
   int nn = *n;
   ColumnVector tmp_f (nn);
   ColumnVector tmp_x (nn);
@@ -80,6 +83,8 @@
 	fvec[i] = tmp_f.elem (i);
     }
 
+  END_INTERRUPT_WITH_EXCEPTIONS;
+
   return 0;
 }
 
@@ -87,6 +92,8 @@
 hybrj1_fcn (int *n, double *x, double *fvec, double *fjac,
 	    int *ldfjac, int *iflag)
 {
+  BEGIN_INTERRUPT_WITH_EXCEPTIONS;
+
   int nn = *n;
   ColumnVector tmp_x (nn);
 
@@ -125,6 +132,8 @@
 	}
     }
 
+  END_INTERRUPT_WITH_EXCEPTIONS;
+
   return 0;
 }
 
--- a/liboctave/ODESSA.cc
+++ b/liboctave/ODESSA.cc
@@ -70,6 +70,8 @@
 odessa_f (int* neq, const double& t, double *state,
 	  double *par, double *fval)
 {
+  BEGIN_INTERRUPT_WITH_EXCEPTIONS;
+
   int n = neq[0];
   int n_par = neq[1];
 
@@ -93,6 +95,8 @@
 	fval[i] = tmp_fval(i);
     }
 
+  END_INTERRUPT_WITH_EXCEPTIONS;
+
   return 0;
 }
 
@@ -101,6 +105,8 @@
 	  double *par, const int& ml, const int& mu, double *pd,
 	  const int& nrowpd)
 {
+  BEGIN_INTERRUPT_WITH_EXCEPTIONS;
+
   int n = neq[0];
   int n_par = neq[1];
 
@@ -124,6 +130,8 @@
 	  pd[nrowpd*j+i] = tmp_fval(i,j);
     }
 
+  END_INTERRUPT_WITH_EXCEPTIONS;
+
   return 0;
 }
 
@@ -132,6 +140,8 @@
 	  double *par, double *dfdp, const int& jpar)
 
 {
+  BEGIN_INTERRUPT_WITH_EXCEPTIONS;
+
   int n = neq[0];
   int n_par = neq[1];
 
@@ -154,6 +164,8 @@
 	dfdp[i] = tmp_fval(i);
     }
 
+  END_INTERRUPT_WITH_EXCEPTIONS;
+
   return 0;
 }
 
--- a/liboctave/Quad.cc
+++ b/liboctave/Quad.cc
@@ -31,6 +31,7 @@
 #include "Quad.h"
 #include "f77-fcn.h"
 #include "lo-error.h"
+#include "quit.h"
 #include "sun-utils.h"
 
 static integrand_fcn user_fcn;
@@ -59,6 +60,8 @@
 static int
 user_function (double *x, int& ierr, double *result)
 {
+  BEGIN_INTERRUPT_WITH_EXCEPTIONS;
+
 #if defined (sun) && defined (__GNUC__)
   double xx = access_double (x);
 #else
@@ -78,6 +81,8 @@
   if (quad_integration_error)
     ierr = -1;
 
+  END_INTERRUPT_WITH_EXCEPTIONS;
+
   return 0;
 }
 
--- a/liboctave/lo-specfun.cc
+++ b/liboctave/lo-specfun.cc
@@ -95,7 +95,7 @@
 acosh (double x)
 {
   double retval;
-  F77_XFCN (xdacosh, XDACOSH, (x, retval));
+  F77_FUNC (xdacosh, XDACOSH) (x, retval);
   return retval;
 }
 #endif
@@ -105,7 +105,7 @@
 asinh (double x)
 {
   double retval;
-  F77_XFCN (xdasinh, XDASINH, (x, retval));
+  F77_FUNC (xdasinh, XDASINH) (x, retval);
   return retval;
 }
 #endif
@@ -115,7 +115,7 @@
 atanh (double x)
 {
   double retval;
-  F77_XFCN (xdatanh, XDATANH, (x, retval));
+  F77_FUNC (xdatanh, XDATANH) (x, retval);
   return retval;
 }
 #endif
@@ -125,7 +125,7 @@
 erf (double x)
 {
   double retval;
-  F77_XFCN (xderf, XDERF, (x, retval));
+  F77_FUNC (xderf, XDERF) (x, retval);
   return retval;
 }
 #endif
@@ -135,7 +135,7 @@
 erfc (double x)
 {
   double retval;
-  F77_XFCN (xderfc, XDERFC, (x, retval));
+  F77_FUNC (xderfc, XDERFC) (x, retval);
   return retval;
 }
 #endif
@@ -144,7 +144,7 @@
 xgamma (double x)
 {
   double result;
-  F77_XFCN (xdgamma, XDGAMMA, (x, result));
+  F77_FUNC (xdgamma, XDGAMMA) (x, result);
   return result;
 }
 
@@ -153,7 +153,7 @@
 {
   double result;
   double sgngam;
-  F77_XFCN (dlgams, DLGAMS, (x, result, sgngam));
+  F77_FUNC (dlgams, DLGAMS) (x, result, sgngam);
   return result;
 }
 
@@ -690,7 +690,7 @@
 betainc (double x, double a, double b)
 {
   double retval;
-  F77_XFCN (xdbetai, XDBETAI, (x, a, b, retval));
+  F77_FUNC (xdbetai, XDBETAI) (x, a, b, retval);
   return retval;
 }
 
@@ -859,7 +859,7 @@
       err = true;
     }
   else
-    F77_XFCN (xgammainc, XGAMMAINC, (a, x, retval));
+    F77_FUNC (xgammainc, XGAMMAINC) (a, x, retval);
 
   return retval;
 }
--- a/src/ChangeLog
+++ b/src/ChangeLog
@@ -1,3 +1,13 @@
+2002-11-14  John W. Eaton  <jwe@bevo.che.wisc.edu>
+
+	* sighandlers.cc (octave_new_handler): Delete.
+	(install_signal_handlers): Don't call set_new_handler.
+	* toplev.cc (main_loop): Handle bad_alloc exception here.
+
+	* sighandlers.cc (octave_new_handler): Allow return after
+	OCTAVE_JUMP_TO_TOP_LEVEL.
+	(sigfpe_handler): Likewise.
+
 2002-11-13  John W. Eaton  <jwe@bevo.che.wisc.edu>
 
 	* variables.cc (is_variable): New static function.
--- a/src/sighandlers.cc
+++ b/src/sighandlers.cc
@@ -124,22 +124,6 @@
     }
 }
 
-// I know, not really a signal handler.
-
-static void
-octave_new_handler (void)
-{
-  std::cerr << "error: memory exhausted -- trying to return to prompt\n";
-
-  if (can_interrupt)
-    {
-      OCTAVE_JUMP_TO_TOP_LEVEL;
-      panic_impossible ();
-    }
-  else
-    my_friendly_exit ("operator new", OCTAVE_MEMORY_EXHAUSTED_ERROR);
-}
-
 sig_handler *
 octave_set_signal_handler (int sig, sig_handler *handler)
 {
@@ -241,8 +225,11 @@
 
   if (can_interrupt)
     {
+      // XXX FIXME XXX -- this may simply set the interrupt state.  We
+      // can only hope for the best after returning?  We probably need
+      // to throw an exception.
+
       OCTAVE_OCTAVE_JUMP_TO_TOP_LEVEL;
-      panic_impossible ();
     }
 
   SIGHANDLER_RETURN (0);
@@ -375,8 +362,6 @@
 void
 install_signal_handlers (void)
 {
-  std::set_new_handler (octave_new_handler);
-
   octave_catch_interrupts ();
 
 #ifdef SIGABRT
--- a/src/toplev.cc
+++ b/src/toplev.cc
@@ -90,6 +90,18 @@
 // Original value of TEXMFDBS environment variable.
 std::string octave_original_texmfdbs;
 
+static void
+recover_from_exception (void)
+{
+  unwind_protect::run_all ();
+  can_interrupt = true;
+  SET_OCTAVE_INTERRUPT_IMMEDIATELY (0);
+  octave_interrupt_state = 0;
+  octave_allocation_error = 0;
+  octave_restore_signal_mask ();
+  octave_catch_interrupts ();
+}
+
 int
 main_loop (void)
 {
@@ -118,7 +130,7 @@
   int retval = 0;
   do
     {
-      OCTAVE_TRY_WITH_INTERRUPTS
+      try
 	{
 	  curr_sym_tab = top_level_sym_tab;
 
@@ -176,13 +188,14 @@
 	}
       OCTAVE_CATCH_INTERRUPTS
 	{
-	  unwind_protect::run_all ();
-	  can_interrupt = true;
-	  SET_OCTAVE_INTERRUPT_IMMEDIATELY (0);
-	  octave_interrupt_state = 0;
+	  recover_from_exception ();
 	  std::cout << "\n";
-	  octave_restore_signal_mask ();
-	  octave_catch_interrupts ();
+	}
+      catch (bad_alloc)
+	{
+	  recover_from_exception ();
+	  std::cerr
+	    << "error: memory exhausted -- trying to return to prompt\n";
 	}
     }
   while (retval == 0);