changeset 802:19dfb459d51a

[xemacs-hg @ 2002-04-03 10:47:37 by ben] fix tty problem et al internals/internals.texi: Add section on correctly merging a branch back into the trunk. console-tty.c, eval.c, event-unixoid.c, file-coding.c, file-coding.h, lisp.h, print.c, sysdep.c: Fix data corruption error in print.c from print_depth becoming negative. Borrow primitives internal_bind_int, internal_bind_lisp_object from my stderr-proc ws, soon to be integrated; use them to properly bind print_depth et al. First fix for TTY problem. The basic problem is I switched things so that the TTY I/O is filtered through a coding system, for the support of kterm and such, that speak JIS or similar encodings. (#### I ***swear*** I had this working way back in 19.12.) Anyway, this introduced buffering issues, in which instead of one char being read, it tried to read 1024 chars. I tried setting the stdin descriptor non-blocking, but it doesn't appear to work on Cygwin. (#### Andy, do you know anything about this?) So I fixed it elsewhere. If you get weirdness on the TTY, look in console-tty.c and see how it gets the coding system; maybe there's a way to change it (and if not, there should be!). Also fix warning in sysdep.c.
author ben
date Wed, 03 Apr 2002 10:47:52 +0000
parents 2b676dc88c66
children 9b6b28d87550
files man/ChangeLog man/internals/internals.texi src/ChangeLog src/console-tty.c src/eval.c src/event-unixoid.c src/file-coding.c src/file-coding.h src/lisp.h src/print.c src/sysdep.c
diffstat 11 files changed, 300 insertions(+), 74 deletions(-) [+]
line wrap: on
line diff
--- a/man/ChangeLog	Mon Apr 01 03:59:04 2002 +0000
+++ b/man/ChangeLog	Wed Apr 03 10:47:52 2002 +0000
@@ -1,3 +1,13 @@
+2002-04-03  Ben Wing  <ben@xemacs.org>
+
+	* internals/internals.texi (Top):
+	* internals/internals.texi (How Lisp Objects Are Represented in C):
+	* internals/internals.texi (Techniques for XEmacs Developers):
+	* internals/internals.texi (CVS Techniques):
+	* internals/internals.texi (Merging a Branch into the Trunk):
+	* internals/internals.texi (A Summary of the Various XEmacs Modules):
+	Add section on correctly merging a branch back into the trunk.
+
 2002-03-19  Adrian Aichner  <adrian@xemacs.org>
 
 	* widget.texi (constants): Typo fix.
--- a/man/internals/internals.texi	Mon Apr 01 03:59:04 2002 +0000
+++ b/man/internals/internals.texi	Wed Apr 03 10:47:52 2002 +0000
@@ -117,6 +117,7 @@
 * The XEmacs Object System (Abstractly Speaking)::
 * How Lisp Objects Are Represented in C::
 * Rules When Writing New C Code::
+* CVS Techniques::
 * A Summary of the Various XEmacs Modules::
 * Allocation of Objects in XEmacs Lisp::
 * Dumping::
@@ -154,7 +155,9 @@
 
 * General Coding Rules::
 * Writing Lisp Primitives::
+* Writing Good Comments::
 * Adding Global Lisp Variables::
+* Proper Use of Unsigned Types::
 * Coding for Mule::
 * Techniques for XEmacs Developers::
 
@@ -166,6 +169,10 @@
 * General Guidelines for Writing Mule-Aware Code::
 * An Example of Mule-Aware Code::
 
+CVS Techniques
+
+* Merging a Branch into the Trunk::
+
 A Summary of the Various XEmacs Modules
 
 * Low-Level Modules::
@@ -1839,7 +1846,7 @@
 nothing unless the corresponding configure error checking flag was
 specified.
 
-@node Rules When Writing New C Code, A Summary of the Various XEmacs Modules, How Lisp Objects Are Represented in C, Top
+@node Rules When Writing New C Code, CVS Techniques, How Lisp Objects Are Represented in C, Top
 @chapter Rules When Writing New C Code
 @cindex writing new C code, rules when
 @cindex C code, rules when writing new
@@ -3096,7 +3103,97 @@
 add an INIT_LRECORD_IMPLEMENTATION call to @code{syms_of_@var{foo}.c}
 @end enumerate
 
-@node A Summary of the Various XEmacs Modules, Allocation of Objects in XEmacs Lisp, Rules When Writing New C Code, Top
+@node CVS Techniques, A Summary of the Various XEmacs Modules, Rules When Writing New C Code, Top
+@chapter CVS Techniques
+@cindex CVS techniques
+
+@menu
+* Merging a Branch into the Trunk::
+@end menu
+
+@node Merging a Branch into the Trunk
+@section Merging a Branch into the Trunk
+@cindex merging a branch into the trunk
+
+@enumerate
+@item
+If you haven't already done a merge, you will be merging from the branch
+point; otherwise you'll be merging from the last merge point, which
+should be marked by a tag, e.g. @samp{last-sync-ben-mule-21-5}.  In the
+former case, create the last-sync tag, e.g.
+
+@example
+crw rtag -r ben-mule-21-5-bp last-sync-ben-mule-21-5 xemacs
+@end example
+
+(You did create a branch point tag when you created the branch, didn't
+you?)
+
+@item
+Check everything in on your branch.
+
+@item
+Tag your branch with a pre-sync tag, e.g.
+
+@example
+crw rtag -r ben-mule-21-5 ben-mule-21-5-pre-feb-20-2002-sync xemacs
+@end example
+
+Note, you need to use rtag and specify a version with @samp{-r} (use
+@samp{-r HEAD} if necessary) so that removed files are handled correctly
+in some obscure cases.  See section 4.8 of the CVS manual.
+
+@item
+Tag the trunk so you have a stable place to merge up to in case people
+are asynchronously committing to the trunk, e.g.
+
+@example
+crw rtag -r HEAD main-branch-ben-mule-21-5-syncpoint-feb-20-2002 xemacs
+crw rtag -F -r main-branch-ben-mule-21-5-syncpoint-feb-20-2002 next-sync-ben-mule-21-5 xemacs
+@end example
+
+Use -F in the second case because the name might already exist, e.g. if
+you've already done a merge.  We make two tags because one is a
+permanent mark indicating a syncpoint when merging, and the other is a
+symbolic tag to make other operations easier.
+
+@item
+Make a backup of your source tree (not totally necessary but useful for
+reference and peace of mind): Move one level up from the top directory
+of your branch and do, e.g.
+
+@example
+cp -a mule mule-backup-2-23-02
+@end example
+
+@item
+Now, we're ready to merge!  Make sure you're in the top directory of
+your branch and do, e.g.
+
+@example
+cvs update -j last-sync-ben-mule-21-5 -j next-sync-ben-mule-21-5
+@end example
+
+@item
+Fix all merge conflicts.  Get the sucker to compile and run.
+
+@item
+Tag your branch with a post-sync tag, e.g.
+
+@example
+crw rtag -r ben-mule-21-5 ben-mule-21-5-post-feb-20-2002-sync xemacs
+@end example
+
+@item
+Update the last-sync tag, e.g.
+
+@example
+crw rtag -F -r next-sync-ben-mule-21-5 last-sync-ben-mule-21-5 xemacs
+@end example
+@end enumerate
+
+
+@node A Summary of the Various XEmacs Modules, Allocation of Objects in XEmacs Lisp, CVS Techniques, Top
 @chapter A Summary of the Various XEmacs Modules
 @cindex modules, a summary of the various XEmacs
 
--- a/src/ChangeLog	Mon Apr 01 03:59:04 2002 +0000
+++ b/src/ChangeLog	Wed Apr 03 10:47:52 2002 +0000
@@ -1,4 +1,49 @@
-2002-03-31  Ben Wing  <ben@xemacs.org>
+2002-04-03  Ben Wing  <ben@xemacs.org>
+
+	* console-tty.c (tty_init_console):
+	* eval.c:
+	* eval.c (restore_lisp_object):
+	* eval.c (restore_int):
+	* eval.c (record_unwind_protect_restoring_int):
+	* event-unixoid.c (read_event_from_tty_or_stream_desc):
+	* file-coding.c (coding_reader):
+	* file-coding.c (make_coding_stream_1):
+	* file-coding.c (make_coding_input_stream):
+	* file-coding.c (make_coding_output_stream):
+	* file-coding.c (detect_coding_stream):
+	* file-coding.h:
+	* file-coding.h (DETECTOR_HAS_METHOD):
+	* file-coding.h (struct coding_stream):
+	* lisp.h:
+	* print.c (Fprin1):
+	* print.c (Fprin1_to_string):
+	* print.c (Fprinc):
+	* print.c (Fprint):
+	* print.c (print_internal):
+	* print.c (debug_print_no_newline):
+	* print.c (debug_backtrace):
+	* sysdep.c (total_data_usage):
+
+	Fix data corruption error in print.c from print_depth becoming
+	negative.  Borrow primitives internal_bind_int,
+	internal_bind_lisp_object from my stderr-proc ws, soon to be
+	integrated; use them to properly bind print_depth et al.
+
+	First fix for TTY problem.  The basic problem is I switched things
+	so that the TTY I/O is filtered through a coding system, for the
+	support of kterm and such, that speak JIS or similar
+	encodings. (#### I ***swear*** I had this working way back in
+	19.12.) Anyway, this introduced buffering issues, in which instead
+	of one char being read, it tried to read 1024 chars.  I tried
+	setting the stdin descriptor non-blocking, but it doesn't appear
+	to work on Cygwin. (#### Andy, do you know anything about this?) 
+	So I fixed it elsewhere.  If you get weirdness on the TTY, look in
+	console-tty.c and see how it gets the coding system; maybe there's
+	a way to change it (and if not, there should be!).
+
+	Also fix warning in sysdep.c.
+
+	2002-03-31  Ben Wing  <ben@xemacs.org>
 
 	* alloc.c:
 	* alloc.c (INCREMENT_CONS_COUNTER):
--- a/src/console-tty.c	Mon Apr 01 03:59:04 2002 +0000
+++ b/src/console-tty.c	Wed Apr 03 10:47:52 2002 +0000
@@ -111,12 +111,13 @@
       tty_con->is_stdio = 0;
     }
 
+  /* set_descriptor_non_blocking (tty_con->infd); */
   tty_con->instream  = make_filedesc_input_stream  (tty_con->infd,  0, -1, 0);
   Lstream_set_buffering (XLSTREAM (tty_con->instream), LSTREAM_UNBUFFERED, 0);
   tty_con->instream =
     make_coding_input_stream (XLSTREAM (tty_con->instream),
 			      get_coding_system_for_text_file (Qkeyboard, 0),
-			      CODING_DECODE, 0);
+			      CODING_DECODE, CODE_FL_READ_ONE_BYTE_AT_A_TIME);
   Lstream_set_buffering (XLSTREAM (tty_con->instream), LSTREAM_UNBUFFERED, 0);
   Lstream_set_character_mode (XLSTREAM (tty_con->instream));
   tty_con->outstream = make_filedesc_output_stream (tty_con->outfd, 0, -1, 0);
--- a/src/eval.c	Mon Apr 01 03:59:04 2002 +0000
+++ b/src/eval.c	Wed Apr 03 10:47:52 2002 +0000
@@ -4906,6 +4906,95 @@
 }
 
 static Lisp_Object
+restore_lisp_object (Lisp_Object cons)
+{
+  Lisp_Object opaque = XCAR (cons);
+  Lisp_Object *addr = (Lisp_Object *) get_opaque_ptr (opaque);
+  *addr = XCDR (cons);
+  free_opaque_ptr (opaque);
+  free_cons (XCONS (cons));
+  return Qnil;
+}
+
+/* Establish an unwind-protect which will restore the Lisp_Object pointed to
+   by ADDR with the value VAL. */
+int
+record_unwind_protect_restoring_lisp_object (Lisp_Object *addr,
+					     Lisp_Object val)
+{
+  Lisp_Object opaque = make_opaque_ptr (addr);
+  return record_unwind_protect (restore_lisp_object,
+				noseeum_cons (opaque, val));
+}
+
+/* Similar to specbind() but for any C variable whose value is a
+   Lisp_Object.  Sets up an unwind-protect to restore the variable
+   pointed to by ADDR to its existing value, and then changes its
+   value to NEWVAL.  Returns the previous value of specpdl_depth();
+   pass this to unbind_to() after you are done. */
+int
+internal_bind_lisp_object (Lisp_Object *addr, Lisp_Object newval)
+{
+  int count = specpdl_depth ();
+  record_unwind_protect_restoring_lisp_object (addr, *addr);
+  *addr = newval;
+  return count;
+}
+
+static Lisp_Object
+restore_int (Lisp_Object cons)
+{
+  Lisp_Object opaque = XCAR (cons);
+  Lisp_Object lval = XCDR (cons);
+  int *addr = (int *) get_opaque_ptr (opaque);
+  int val;
+
+  if (INTP (lval))
+    val = XINT (lval);
+  else
+    {
+      val = (int) get_opaque_ptr (lval);
+      free_opaque_ptr (lval);
+    }
+
+  *addr = val;
+  free_opaque_ptr (opaque);
+  free_cons (XCONS (cons));
+  return Qnil;
+}
+
+/* Establish an unwind-protect which will restore the int pointed to
+   by ADDR with the value VAL.  This function works correctly with
+   all ints, even those that don't fit into a Lisp integer. */
+int
+record_unwind_protect_restoring_int (int *addr, int val)
+{
+  Lisp_Object opaque = make_opaque_ptr (addr);
+  Lisp_Object lval;
+
+  if (NUMBER_FITS_IN_AN_EMACS_INT (val))
+    lval = make_int (val);
+  else
+    lval = make_opaque_ptr ((void *) val);
+  return record_unwind_protect (restore_int, noseeum_cons (opaque, lval));
+}
+
+/* Similar to specbind() but for any C variable whose value is an int.
+   Sets up an unwind-protect to restore the variable pointed to by
+   ADDR to its existing value, and then changes its value to NEWVAL.
+   Returns the previous value of specpdl_depth(); pass this to
+   unbind_to() after you are done.  This function works correctly with
+   all ints, even those that don't fit into a Lisp integer. */
+int
+internal_bind_int (int *addr, int newval)
+{
+  int count = specpdl_depth ();
+  record_unwind_protect_restoring_int (addr, *addr);
+  *addr = newval;
+  return count;
+}
+
+static Lisp_Object
 free_pointer (Lisp_Object opaque)
 {
   xfree (get_opaque_ptr (opaque));
--- a/src/event-unixoid.c	Mon Apr 01 03:59:04 2002 +0000
+++ b/src/event-unixoid.c	Wed Apr 03 10:47:52 2002 +0000
@@ -76,7 +76,6 @@
   Emchar ch;
   Lisp_Object console = wrap_console (con);
 
-
   if (CONSOLE_TTY_P (con))
     ch = Lstream_get_emchar (XLSTREAM (CONSOLE_TTY_DATA (con)->instream));
   else
--- a/src/file-coding.c	Mon Apr 01 03:59:04 2002 +0000
+++ b/src/file-coding.c	Wed Apr 03 10:47:52 2002 +0000
@@ -2037,7 +2037,7 @@
            and when we get 0, keep taking more data until we don't get 0 --
            we don't know how much data the conversion routine might need
            before it can generate any data of its own */
-	Bytecount readmore = max (size, 1024);
+	Bytecount readmore = max (size, str->one_byte_at_a_time ? 1 : 1024);
 
 	Dynarr_add_many (str->convert_from, 0, readmore);
 	read_size = Lstream_read (str->other_end,
@@ -2305,7 +2305,7 @@
 static Lisp_Object
 make_coding_stream_1 (Lstream *stream, Lisp_Object codesys,
 		      const char *mode, enum encode_decode direction,
-		      int no_close_other)
+		      int flags)
 {
   Lstream *lstr = Lstream_new (lstream_coding, mode);
   struct coding_stream *str = CODING_STREAM_DATA (lstr);
@@ -2319,29 +2319,33 @@
   str->convert_to = Dynarr_new (unsigned_char);
   str->convert_from = Dynarr_new (unsigned_char);
   str->direction = direction;
-  str->no_close_other = no_close_other;
+  if (flags & CODE_FL_NO_CLOSE_OTHER)
+    str->no_close_other = 1;
+  else if (flags & CODE_FL_READ_ONE_BYTE_AT_A_TIME)
+    str->one_byte_at_a_time = 1;
+    
   set_coding_stream_coding_system (lstr, codesys);
   return wrap_lstream (lstr);
 }
 
-/* If NO_CLOSE_OTHER is non-zero, don't close STREAM (the stream at the
-   other end) when this stream is closed. */
+/* FLAGS -- #### document me.  If NO_CLOSE_OTHER is non-zero, don't close
+   STREAM (the stream at the other end) when this stream is closed. */
 Lisp_Object
 make_coding_input_stream (Lstream *stream, Lisp_Object codesys,
-			  enum encode_decode direction, int no_close_other)
+			  enum encode_decode direction, int flags)
 {
   return make_coding_stream_1 (stream, codesys, "r", direction,
-                               no_close_other);
+                               flags);
 }
 
-/* If NO_CLOSE_OTHER is non-zero, don't close STREAM (the stream at the
-   other end) when this stream is closed. */
+/* FLAGS -- #### document me.  If NO_CLOSE_OTHER is non-zero, don't close
+   STREAM (the stream at the other end) when this stream is closed. */
 Lisp_Object
 make_coding_output_stream (Lstream *stream, Lisp_Object codesys,
-			  enum encode_decode direction, int no_close_other)
+			  enum encode_decode direction, int flags)
 {
   return make_coding_stream_1 (stream, codesys, "w", direction,
-                               no_close_other);
+                               flags);
 }
 
 static Lisp_Object
@@ -4147,7 +4151,7 @@
   Lisp_Object binary_instream =
     make_coding_input_stream
       (XLSTREAM (stream), Qbinary,
-       CODING_ENCODE, 1);
+       CODING_ENCODE, CODE_FL_NO_CLOSE_OTHER);
   Lisp_Object decstream =
     make_coding_input_stream 
       (XLSTREAM (binary_instream),
--- a/src/file-coding.h	Mon Apr 01 03:59:04 2002 +0000
+++ b/src/file-coding.h	Wed Apr 03 10:47:52 2002 +0000
@@ -836,7 +836,7 @@
 } while (0)
 #define DETECTOR_HAS_METHOD(Detector, Meth)				\
   Dynarr_at (all_coding_detectors, detector_##Detector).Meth##_method =	\
-  Detector##_##Meth
+    Detector##_##Meth
   
 
 /**************************************************/
@@ -930,6 +930,9 @@
 
   /* If set, don't close the stream at the other end when being closed. */
   unsigned int no_close_other:1;
+  /* If set, read only one byte at a time from other end to avoid any
+     possible blocking. */
+  unsigned int one_byte_at_a_time:1;
   
   /* #### Temporary test */
   unsigned int finalized:1;
@@ -1057,12 +1060,15 @@
 					 Lisp_Object type,
 					 Lisp_Object description,
 					 Lisp_Object props);
+
+#define CODE_FL_NO_CLOSE_OTHER (1 << 0)
+#define CODE_FL_READ_ONE_BYTE_AT_A_TIME (1 << 1)
 Lisp_Object make_coding_input_stream (Lstream *stream, Lisp_Object codesys,
 				      enum encode_decode direction,
-				      int no_close_other);
+				      int flags);
 Lisp_Object make_coding_output_stream (Lstream *stream, Lisp_Object codesys,
 				       enum encode_decode direction,
-				       int no_close_other);
+				       int flags);
 void set_detection_results (struct detection_state *st, int detector,
 			    int given);
 
--- a/src/lisp.h	Mon Apr 01 03:59:04 2002 +0000
+++ b/src/lisp.h	Wed Apr 03 10:47:52 2002 +0000
@@ -774,6 +774,9 @@
 #define VALBITS (BITS_PER_EMACS_INT - GCBITS)
 #define EMACS_INT_MAX ((EMACS_INT) ((1UL << (INT_VALBITS - 1)) -1UL))
 #define EMACS_INT_MIN (-(EMACS_INT_MAX) - 1)
+/* WARNING: evaluates its arg twice. */
+#define NUMBER_FITS_IN_AN_EMACS_INT(num) \
+  ((num) <= EMACS_INT_MAX && (num) >= EMACS_INT_MIN)
 
 #ifdef USE_UNION_TYPE
 # include "lisp-union.h"
@@ -3070,6 +3073,8 @@
 int record_unwind_protect (Lisp_Object (*) (Lisp_Object), Lisp_Object);
 int record_unwind_protect_freeing (void *ptr);
 int record_unwind_protect_freeing_dynarr (void *ptr);
+int internal_bind_int (int *addr, int newval);
+int internal_bind_lisp_object (Lisp_Object *addr, Lisp_Object newval);
 void do_autoload (Lisp_Object, Lisp_Object);
 Lisp_Object un_autoload (Lisp_Object);
 void warn_when_safe_lispobj (Lisp_Object, Lisp_Object, Lisp_Object);
--- a/src/print.c	Mon Apr 01 03:59:04 2002 +0000
+++ b/src/print.c	Wed Apr 03 10:47:52 2002 +0000
@@ -762,7 +762,6 @@
   struct gcpro gcpro1, gcpro2;
   GCPRO2 (object, stream);
 
-  print_depth = 0;
   stream = print_prepare (stream, &frame);
   print_internal (object, stream, 1);
   print_finish (stream, frame);
@@ -787,7 +786,6 @@
   struct gcpro gcpro1, gcpro2, gcpro3;
   GCPRO3 (object, stream, result);
 
-  print_depth = 0;
   RESET_PRINT_GENSYM;
   print_internal (object, stream, NILP (noescape));
   RESET_PRINT_GENSYM;
@@ -813,7 +811,6 @@
 
   GCPRO2 (object, stream);
   stream = print_prepare (stream, &frame);
-  print_depth = 0;
   print_internal (object, stream, 0);
   print_finish (stream, frame);
   UNGCPRO;
@@ -834,7 +831,6 @@
 
   GCPRO2 (object, stream);
   stream = print_prepare (stream, &frame);
-  print_depth = 0;
   write_char_internal ("\n", stream);
   print_internal (object, stream, 1);
   write_char_internal ("\n", stream);
@@ -1388,6 +1384,7 @@
 print_internal (Lisp_Object obj, Lisp_Object printcharfun, int escapeflag)
 {
   /* This function can GC */
+  int specdepth;
 
   QUIT;
 
@@ -1481,7 +1478,7 @@
     }
 
   being_printed[print_depth] = obj;
-  print_depth++;
+  specdepth = internal_bind_int (&print_depth, print_depth + 1);
 
   if (print_depth > PRINT_CIRCLE)
     signal_error (Qstack_overflow, "Apparently circular structure being printed", Qunbound);
@@ -1610,7 +1607,7 @@
       }
     }
 
-  print_depth--;
+  unbind_to (specdepth);
 }
 
 
@@ -1890,23 +1887,17 @@
 debug_print_no_newline (Lisp_Object debug_print_obj)
 {
   /* This function can GC */
-  int save_print_readably = print_readably;
-  int save_print_depth    = print_depth;
-  Lisp_Object save_Vprint_length = Vprint_length;
-  Lisp_Object save_Vprint_level  = Vprint_level;
-  Lisp_Object save_Vinhibit_quit = Vinhibit_quit;
-  struct gcpro gcpro1, gcpro2, gcpro3;
-  GCPRO3 (save_Vprint_level, save_Vprint_length, save_Vinhibit_quit);
-
-  print_depth = 0;
-  print_readably = debug_print_readably != -1 ? debug_print_readably : 0;
-  print_unbuffered++;
-  /* Could use unwind-protect, but why bother? */
+  int specdepth = internal_bind_int (&print_depth, 0);
+  internal_bind_int (&print_readably,
+		     debug_print_readably != -1 ? debug_print_readably : 0);
+  internal_bind_int (&print_unbuffered, print_unbuffered + 1);
   if (debug_print_length > 0)
-    Vprint_length = make_int (debug_print_length);
+    internal_bind_lisp_object (&Vprint_length, make_int (debug_print_length));
   if (debug_print_level > 0)
-    Vprint_level = make_int (debug_print_level);
-
+    internal_bind_lisp_object (&Vprint_level, make_int (debug_print_level));
+  /* #### Do we need this?  It was in the old code. */
+  internal_bind_lisp_object (&Vinhibit_quit, Vinhibit_quit);
+  
   print_internal (debug_print_obj, Qexternal_debugging_output, 1);
   alternate_do_pointer = 0;
   print_internal (debug_print_obj, Qalternate_debugging_output, 1);
@@ -1915,13 +1906,7 @@
   print_internal (debug_print_obj, Qmswindows_debugging_output, 1);
 #endif
 
-  Vinhibit_quit  = save_Vinhibit_quit;
-  Vprint_level   = save_Vprint_level;
-  Vprint_length  = save_Vprint_length;
-  print_depth    = save_print_depth;
-  print_readably = save_print_readably;
-  print_unbuffered--;
-  UNGCPRO;
+  unbind_to (specdepth);
 }
 
 void
@@ -1937,35 +1922,20 @@
 debug_backtrace (void)
 {
   /* This function can GC */
-  int         old_print_readably = print_readably;
-  int         old_print_depth    = print_depth;
-  Lisp_Object old_print_length   = Vprint_length;
-  Lisp_Object old_print_level    = Vprint_level;
-  Lisp_Object old_inhibit_quit   = Vinhibit_quit;
-
-  struct gcpro gcpro1, gcpro2, gcpro3;
-  GCPRO3 (old_print_level, old_print_length, old_inhibit_quit);
-
-  print_depth = 0;
-  print_readably = 0;
-  print_unbuffered++;
-  /* Could use unwind-protect, but why bother? */
+  int specdepth = internal_bind_int (&print_depth, 0);
+  internal_bind_int (&print_readably, 0);
+  internal_bind_int (&print_unbuffered, print_unbuffered + 1);
   if (debug_print_length > 0)
-    Vprint_length = make_int (debug_print_length);
+    internal_bind_lisp_object (&Vprint_length, make_int (debug_print_length));
   if (debug_print_level > 0)
-    Vprint_level = make_int (debug_print_level);
+    internal_bind_lisp_object (&Vprint_level, make_int (debug_print_level));
+  /* #### Do we need this?  It was in the old code. */
+  internal_bind_lisp_object (&Vinhibit_quit, Vinhibit_quit);
 
   Fbacktrace (Qexternal_debugging_output, Qt);
   stderr_out ("\n");
 
-  Vinhibit_quit  = old_inhibit_quit;
-  Vprint_level   = old_print_level;
-  Vprint_length  = old_print_length;
-  print_depth    = old_print_depth;
-  print_readably = old_print_readably;
-  print_unbuffered--;
-
-  UNGCPRO;
+  unbind_to (specdepth);
 }
 
 void
--- a/src/sysdep.c	Mon Apr 01 03:59:04 2002 +0000
+++ b/src/sysdep.c	Wed Apr 03 10:47:52 2002 +0000
@@ -2234,9 +2234,6 @@
 Bytecount
 total_data_usage (void)
 {
-  static EMACS_INT last_consing_since_gc;
-  static void *last_sbrk;
-
 #ifdef NEED_STARTS
   void *data_start = start_of_data ();
 #else
@@ -2246,6 +2243,9 @@
 #if !defined (WIN32_NATIVE) && !defined (CYGWIN)
   void *data_end;
 
+  static EMACS_INT last_consing_since_gc;
+  static void *last_sbrk;
+
   /* Random hack to avoid calling sbrk constantly (every funcall).  #### Is
      it worth it? */
   if (!last_sbrk || !(consing_since_gc >= last_consing_since_gc &&