+/* ------------------------------- */
+/* low-level debugging functions */
+/* ------------------------------- */
+
+#if defined (WIN32_NATIVE) && defined (DEBUG_XEMACS)
+#define debugging_breakpoint() DebugBreak ()
+#else
+#define debugging_breakpoint()
+#endif
+
+void
+debug_break (void)
+{
+ debugging_breakpoint ();
+}
+
+#if defined (WIN32_NATIVE) || defined (CYGWIN)
+
+/* Return whether all bytes in the specified memory block can be read. */
+int
+debug_can_access_memory (void *ptr, Bytecount len)
+{
+ return !IsBadReadPtr (ptr, len);
+}
+
+#else /* !(defined (WIN32_NATIVE) || defined (CYGWIN)) */
+
+/* #### There must be a better way!!!! */
+
+static JMP_BUF memory_error_jump;
+
+static SIGTYPE
+debug_memory_error (int signum)
+{
+ EMACS_REESTABLISH_SIGNAL (signum, debug_memory_error);
+ EMACS_UNBLOCK_SIGNAL (signum);
+ LONGJMP (memory_error_jump, 1);
+}
+
+/* Return whether all bytes in the specified memory block can be read. */
+int
+debug_can_access_memory (void *ptr, Bytecount len)
+{
+ /* Use volatile to protect variables from being clobbered by longjmp. */
+ SIGTYPE (*volatile old_sigbus) (int);
+ SIGTYPE (*volatile old_sigsegv) (int);
+ volatile int old_errno = errno;
+ volatile int retval = 1;
+
+ if (!SETJMP (memory_error_jump))
+ {
+ old_sigbus =
+ (SIGTYPE (*) (int)) signal (SIGBUS, debug_memory_error);
+ old_sigsegv =
+ (SIGTYPE (*) (int)) signal (SIGSEGV, debug_memory_error);
+
+ if (len > 1)
+ /* If we can, try to avoid problems with super-optimizing compilers
+ that might decide that memcmp (ptr, ptr, len) can be optimized
+ away since its result is always 1. */
+ memcmp (ptr, (char *) ptr + 1, len - 1);
+ else
+ memcmp (ptr, ptr, len);
+ }
+ else
+ retval = 0;
+ signal (SIGBUS, old_sigbus);
+ signal (SIGSEGV, old_sigsegv);
+ errno = old_errno;
+
+ return retval;
+}
+
+#endif /* defined (WIN32_NATIVE) || defined (CYGWIN) */
+
+#ifdef DEBUG_XEMACS
+
+DEFUN ("force-debugging-signal", Fforce_debugging_signal, 0, 1, 0, /*
+Cause XEmacs to enter the debugger.
+On some systems, there may be no way to do this gracefully; if so,
+nothing happens unless ABORT is non-nil, in which case XEmacs will
+ABORT() -- a sure-fire way to immediately get back to the debugger,
+but also a sure-fire way to kill XEmacs (and dump core on Unix
+systems)!
+*/
+ (abort_))
+{
+ debugging_breakpoint ();
+ if (!NILP (abort_))
+ ABORT ();
+ return Qnil;
+}
+
+#endif /* DEBUG_XEMACS */
+