]> code.delx.au - gnu-emacs/blobdiff - src/print.c
Use fast_string_match_ignore_case for comparing font names.
[gnu-emacs] / src / print.c
index 74447387df476f9e6bc14d5179af1ddfee13733e..5a0f7fe6220117f4efbaee2c799a853251a1453c 100644 (file)
@@ -1,5 +1,5 @@
 /* Lisp object printing and output streams.
 /* Lisp object printing and output streams.
-   Copyright (C) 1985, 86, 88, 93, 94, 95, 97, 98, 1999, 2000, 2001
+   Copyright (C) 1985, 86, 88, 93, 94, 95, 97, 98, 1999, 2000, 01, 03, 2004
        Free Software Foundation, Inc.
 
 This file is part of GNU Emacs.
        Free Software Foundation, Inc.
 
 This file is part of GNU Emacs.
@@ -91,6 +91,9 @@ Lisp_Object Vfloat_output_format, Qfloat_output_format;
 /* Avoid actual stack overflow in print.  */
 int print_depth;
 
 /* Avoid actual stack overflow in print.  */
 int print_depth;
 
+/* Nonzero if inside outputting backquote in old style.  */
+int old_backquote_output;
+
 /* Detect most circularities to print finite output.  */
 #define PRINT_CIRCLE 200
 Lisp_Object being_printed[PRINT_CIRCLE];
 /* Detect most circularities to print finite output.  */
 #define PRINT_CIRCLE 200
 Lisp_Object being_printed[PRINT_CIRCLE];
@@ -186,13 +189,13 @@ void print_interval ();
    and must start with PRINTPREPARE, end with PRINTFINISH,
    and use PRINTDECLARE to declare common variables.
    Use PRINTCHAR to output one character,
    and must start with PRINTPREPARE, end with PRINTFINISH,
    and use PRINTDECLARE to declare common variables.
    Use PRINTCHAR to output one character,
-   or call strout to output a block of characters. */ 
+   or call strout to output a block of characters. */
 
 #define PRINTDECLARE                                                   \
    struct buffer *old = current_buffer;                                        \
    int old_point = -1, start_point = -1;                               \
    int old_point_byte = -1, start_point_byte = -1;                     \
 
 #define PRINTDECLARE                                                   \
    struct buffer *old = current_buffer;                                        \
    int old_point = -1, start_point = -1;                               \
    int old_point_byte = -1, start_point_byte = -1;                     \
-   int specpdl_count = specpdl_ptr - specpdl;                          \
+   int specpdl_count = SPECPDL_INDEX ();                               \
    int free_print_buffer = 0;                                          \
    int multibyte = !NILP (current_buffer->enable_multibyte_characters);        \
    Lisp_Object original
    int free_print_buffer = 0;                                          \
    int multibyte = !NILP (current_buffer->enable_multibyte_characters);        \
    Lisp_Object original
@@ -290,7 +293,7 @@ static Lisp_Object
 print_unwind (saved_text)
      Lisp_Object saved_text;
 {
 print_unwind (saved_text)
      Lisp_Object saved_text;
 {
-  bcopy (XSTRING (saved_text)->data, print_buffer, XSTRING (saved_text)->size);
+  bcopy (SDATA (saved_text), print_buffer, SCHARS (saved_text));
   return Qnil;
 }
 
   return Qnil;
 }
 
@@ -318,7 +321,7 @@ printchar (ch, fun)
       int len = CHAR_STRING (ch, str);
 
       QUIT;
       int len = CHAR_STRING (ch, str);
 
       QUIT;
-      
+
       if (NILP (fun))
        {
          if (print_buffer_pos_byte + len >= print_buffer_size)
       if (NILP (fun))
        {
          if (print_buffer_pos_byte + len >= print_buffer_size)
@@ -337,7 +340,7 @@ printchar (ch, fun)
        {
          int multibyte_p
            = !NILP (current_buffer->enable_multibyte_characters);
        {
          int multibyte_p
            = !NILP (current_buffer->enable_multibyte_characters);
-         
+
          setup_echo_area_for_printing (multibyte_p);
          insert_char (ch);
          message_dolog (str, len, 0, multibyte_p);
          setup_echo_area_for_printing (multibyte_p);
          insert_char (ch);
          message_dolog (str, len, 0, multibyte_p);
@@ -394,10 +397,10 @@ strout (ptr, size, size_byte, printcharfun, multibyte)
       int i;
       int multibyte_p
        = !NILP (current_buffer->enable_multibyte_characters);
       int i;
       int multibyte_p
        = !NILP (current_buffer->enable_multibyte_characters);
-      
+
       setup_echo_area_for_printing (multibyte_p);
       message_dolog (ptr, size_byte, 0, multibyte_p);
       setup_echo_area_for_printing (multibyte_p);
       message_dolog (ptr, size_byte, 0, multibyte_p);
-      
+
       if (size == size_byte)
        {
          for (i = 0; i < size; ++i)
       if (size == size_byte)
        {
          for (i = 0; i < size; ++i)
@@ -412,7 +415,7 @@ strout (ptr, size, size_byte, printcharfun, multibyte)
              insert_char (ch);
            }
        }
              insert_char (ch);
            }
        }
-      
+
 #ifdef MAX_PRINT_CHARS
       if (max_print)
         print_chars += size;
 #ifdef MAX_PRINT_CHARS
       if (max_print)
         print_chars += size;
@@ -461,7 +464,7 @@ print_string (string, printcharfun)
       int chars;
 
       if (STRING_MULTIBYTE (string))
       int chars;
 
       if (STRING_MULTIBYTE (string))
-       chars = XSTRING (string)->size;
+       chars = SCHARS (string);
       else if (EQ (printcharfun, Qt)
               ? ! NILP (buffer_defaults.enable_multibyte_characters)
               : ! NILP (current_buffer->enable_multibyte_characters))
       else if (EQ (printcharfun, Qt)
               ? ! NILP (buffer_defaults.enable_multibyte_characters)
               : ! NILP (current_buffer->enable_multibyte_characters))
@@ -472,22 +475,22 @@ print_string (string, printcharfun)
          Lisp_Object newstr;
          int bytes;
 
          Lisp_Object newstr;
          int bytes;
 
-         chars = STRING_BYTES (XSTRING (string));
-         bytes = parse_str_to_multibyte (XSTRING (string)->data, chars);
+         chars = SBYTES (string);
+         bytes = parse_str_to_multibyte (SDATA (string), chars);
          if (chars < bytes)
            {
              newstr = make_uninit_multibyte_string (chars, bytes);
          if (chars < bytes)
            {
              newstr = make_uninit_multibyte_string (chars, bytes);
-             bcopy (XSTRING (string)->data, XSTRING (newstr)->data, chars);
-             str_to_multibyte (XSTRING (newstr)->data, bytes, chars);
+             bcopy (SDATA (string), SDATA (newstr), chars);
+             str_to_multibyte (SDATA (newstr), bytes, chars);
              string = newstr;
            }
        }
       else
              string = newstr;
            }
        }
       else
-       chars = STRING_BYTES (XSTRING (string));
+       chars = SBYTES (string);
 
       /* strout is safe for output to a frame (echo area) or to print_buffer.  */
 
       /* strout is safe for output to a frame (echo area) or to print_buffer.  */
-      strout (XSTRING (string)->data,
-             chars, STRING_BYTES (XSTRING (string)),
+      strout (SDATA (string),
+             chars, SBYTES (string),
              printcharfun, STRING_MULTIBYTE (string));
     }
   else
              printcharfun, STRING_MULTIBYTE (string));
     }
   else
@@ -495,24 +498,24 @@ print_string (string, printcharfun)
       /* Otherwise, string may be relocated by printing one char.
         So re-fetch the string address for each character.  */
       int i;
       /* Otherwise, string may be relocated by printing one char.
         So re-fetch the string address for each character.  */
       int i;
-      int size = XSTRING (string)->size;
-      int size_byte = STRING_BYTES (XSTRING (string));
+      int size = SCHARS (string);
+      int size_byte = SBYTES (string);
       struct gcpro gcpro1;
       GCPRO1 (string);
       if (size == size_byte)
        for (i = 0; i < size; i++)
       struct gcpro gcpro1;
       GCPRO1 (string);
       if (size == size_byte)
        for (i = 0; i < size; i++)
-         PRINTCHAR (XSTRING (string)->data[i]);
+         PRINTCHAR (SREF (string, i));
       else
       else
-       for (i = 0; i < size_byte; i++)
+       for (i = 0; i < size_byte; )
          {
            /* Here, we must convert each multi-byte form to the
               corresponding character code before handing it to PRINTCHAR.  */
            int len;
          {
            /* Here, we must convert each multi-byte form to the
               corresponding character code before handing it to PRINTCHAR.  */
            int len;
-           int ch = STRING_CHAR_AND_LENGTH (XSTRING (string)->data + i,
+           int ch = STRING_CHAR_AND_LENGTH (SDATA (string) + i,
                                             size_byte - i, len);
            if (!CHAR_VALID_P (ch, 0))
              {
                                             size_byte - i, len);
            if (!CHAR_VALID_P (ch, 0))
              {
-               ch = XSTRING (string)->data[i];
+               ch = SREF (string, i);
                len = 1;
              }
            PRINTCHAR (ch);
                len = 1;
              }
            PRINTCHAR (ch);
@@ -578,9 +581,9 @@ write_string_1 (data, size, printcharfun)
 
 void
 temp_output_buffer_setup (bufname)
 
 void
 temp_output_buffer_setup (bufname)
-    char *bufname;
+    const char *bufname;
 {
 {
-  int count = specpdl_ptr - specpdl;
+  int count = SPECPDL_INDEX ();
   register struct buffer *old = current_buffer;
   register Lisp_Object buf;
 
   register struct buffer *old = current_buffer;
   register Lisp_Object buf;
 
@@ -588,19 +591,22 @@ temp_output_buffer_setup (bufname)
 
   Fset_buffer (Fget_buffer_create (build_string (bufname)));
 
 
   Fset_buffer (Fget_buffer_create (build_string (bufname)));
 
+  Fkill_all_local_variables ();
+  delete_all_overlays (current_buffer);
   current_buffer->directory = old->directory;
   current_buffer->read_only = Qnil;
   current_buffer->filename = Qnil;
   current_buffer->undo_list = Qt;
   current_buffer->directory = old->directory;
   current_buffer->read_only = Qnil;
   current_buffer->filename = Qnil;
   current_buffer->undo_list = Qt;
-  current_buffer->overlays_before = Qnil;
-  current_buffer->overlays_after = Qnil;
+  eassert (current_buffer->overlays_before == NULL);
+  eassert (current_buffer->overlays_after == NULL);
   current_buffer->enable_multibyte_characters
     = buffer_defaults.enable_multibyte_characters;
   current_buffer->enable_multibyte_characters
     = buffer_defaults.enable_multibyte_characters;
+  specbind (Qinhibit_read_only, Qt);
+  specbind (Qinhibit_modification_hooks, Qt);
   Ferase_buffer ();
   XSETBUFFER (buf, current_buffer);
 
   Ferase_buffer ();
   XSETBUFFER (buf, current_buffer);
 
-  if (!NILP (Vrun_hooks))
-    call1 (Vrun_hooks, Qtemp_buffer_setup_hook);
+  Frun_hooks (1, &Qtemp_buffer_setup_hook);
 
   unbind_to (count, Qnil);
 
 
   unbind_to (count, Qnil);
 
@@ -609,11 +615,11 @@ temp_output_buffer_setup (bufname)
 
 Lisp_Object
 internal_with_output_to_temp_buffer (bufname, function, args)
 
 Lisp_Object
 internal_with_output_to_temp_buffer (bufname, function, args)
-     char *bufname;
+     const char *bufname;
      Lisp_Object (*function) P_ ((Lisp_Object));
      Lisp_Object args;
 {
      Lisp_Object (*function) P_ ((Lisp_Object));
      Lisp_Object args;
 {
-  int count = specpdl_ptr - specpdl;
+  int count = SPECPDL_INDEX ();
   Lisp_Object buf, val;
   struct gcpro gcpro1;
 
   Lisp_Object buf, val;
   struct gcpro gcpro1;
 
@@ -650,21 +656,21 @@ to display it temporarily selected.
 
 If variable `temp-buffer-show-function' is non-nil, call it at the end
 to get the buffer displayed instead of just displaying the non-selected
 
 If variable `temp-buffer-show-function' is non-nil, call it at the end
 to get the buffer displayed instead of just displaying the non-selected
-buffer and calling the hook.  It gets one argument, the buffer to display.  
+buffer and calling the hook.  It gets one argument, the buffer to display.
 
 
-usage: (with-output-to-temp-buffer BUFFNAME BODY ...)  */)
+usage: (with-output-to-temp-buffer BUFNAME BODY ...)  */)
      (args)
      Lisp_Object args;
 {
   struct gcpro gcpro1;
   Lisp_Object name;
      (args)
      Lisp_Object args;
 {
   struct gcpro gcpro1;
   Lisp_Object name;
-  int count = specpdl_ptr - specpdl;
+  int count = SPECPDL_INDEX ();
   Lisp_Object buf, val;
 
   GCPRO1(args);
   name = Feval (Fcar (args));
   CHECK_STRING (name);
   Lisp_Object buf, val;
 
   GCPRO1(args);
   name = Feval (Fcar (args));
   CHECK_STRING (name);
-  temp_output_buffer_setup (XSTRING (name)->data);
+  temp_output_buffer_setup (SDATA (name));
   buf = Vstandard_output;
   UNGCPRO;
 
   buf = Vstandard_output;
   UNGCPRO;
 
@@ -702,7 +708,8 @@ If PRINTCHARFUN is omitted or nil, the value of `standard-output' is used.  */)
 DEFUN ("prin1", Fprin1, Sprin1, 1, 2, 0,
        doc: /* Output the printed representation of OBJECT, any Lisp object.
 Quoting characters are printed when needed to make output that `read'
 DEFUN ("prin1", Fprin1, Sprin1, 1, 2, 0,
        doc: /* Output the printed representation of OBJECT, any Lisp object.
 Quoting characters are printed when needed to make output that `read'
-can handle, whenever this is possible.
+can handle, whenever this is possible.  For complex objects, the behavior
+is controlled by `print-level' and `print-length', which see.
 
 OBJECT is any of the Lisp data types: a number, a string, a symbol,
 a list, a buffer, a window, a frame, etc.
 
 OBJECT is any of the Lisp data types: a number, a string, a symbol,
 a list, a buffer, a window, a frame, etc.
@@ -743,7 +750,7 @@ Lisp_Object Vprin1_to_string_buffer;
 DEFUN ("prin1-to-string", Fprin1_to_string, Sprin1_to_string, 1, 2, 0,
        doc: /* Return a string containing the printed representation of OBJECT.
 OBJECT can be any Lisp object.  This function outputs quoting characters
 DEFUN ("prin1-to-string", Fprin1_to_string, Sprin1_to_string, 1, 2, 0,
        doc: /* Return a string containing the printed representation of OBJECT.
 OBJECT can be any Lisp object.  This function outputs quoting characters
-when ncessary to make output that `read' can handle, whenever possible,
+when necessary to make output that `read' can handle, whenever possible,
 unless the optional second argument NOESCAPE is non-nil.
 
 OBJECT is any of the Lisp data types: a number, a string, a symbol,
 unless the optional second argument NOESCAPE is non-nil.
 
 OBJECT is any of the Lisp data types: a number, a string, a symbol,
@@ -753,32 +760,48 @@ A printed representation of an object is text which describes that object.  */)
      (object, noescape)
      Lisp_Object object, noescape;
 {
      (object, noescape)
      Lisp_Object object, noescape;
 {
-  PRINTDECLARE;
   Lisp_Object printcharfun;
   Lisp_Object printcharfun;
-  struct gcpro gcpro1, gcpro2;
-  Lisp_Object tem;
+  /* struct gcpro gcpro1, gcpro2; */
+  Lisp_Object save_deactivate_mark;
+  int count = specpdl_ptr - specpdl;
+  struct buffer *previous;
 
 
-  /* Save and restore this--we are altering a buffer
-     but we don't want to deactivate the mark just for that.
-     No need for specbind, since errors deactivate the mark.  */
-  tem = Vdeactivate_mark;
-  GCPRO2 (object, tem);
+  specbind (Qinhibit_modification_hooks, Qt);
 
 
-  printcharfun = Vprin1_to_string_buffer;
-  PRINTPREPARE;
-  print (object, printcharfun, NILP (noescape));
-  /* Make Vprin1_to_string_buffer be the default buffer after PRINTFINSH */
-  PRINTFINISH;
+  {
+    PRINTDECLARE;
+
+    /* Save and restore this--we are altering a buffer
+       but we don't want to deactivate the mark just for that.
+       No need for specbind, since errors deactivate the mark.  */
+    save_deactivate_mark = Vdeactivate_mark;
+    /* GCPRO2 (object, save_deactivate_mark); */
+    abort_on_gc++;
+
+    printcharfun = Vprin1_to_string_buffer;
+    PRINTPREPARE;
+    print (object, printcharfun, NILP (noescape));
+    /* Make Vprin1_to_string_buffer be the default buffer after PRINTFINSH */
+    PRINTFINISH;
+  }
+
+  previous = current_buffer;
   set_buffer_internal (XBUFFER (Vprin1_to_string_buffer));
   object = Fbuffer_string ();
   set_buffer_internal (XBUFFER (Vprin1_to_string_buffer));
   object = Fbuffer_string ();
+  if (SBYTES (object) == SCHARS (object))
+    STRING_SET_UNIBYTE (object);
 
 
+  /* Note that this won't make prepare_to_modify_buffer call
+     ask-user-about-supersession-threat because this buffer
+     does not visit a file.  */
   Ferase_buffer ();
   Ferase_buffer ();
-  set_buffer_internal (old);
+  set_buffer_internal (previous);
 
 
-  Vdeactivate_mark = tem;
-  UNGCPRO;
+  Vdeactivate_mark = save_deactivate_mark;
+  /* UNGCPRO; */
 
 
-  return object;
+  abort_on_gc--;
+  return unbind_to (count, object);
 }
 
 DEFUN ("princ", Fprinc, Sprinc, 1, 2, 0,
 }
 
 DEFUN ("princ", Fprinc, Sprinc, 1, 2, 0,
@@ -819,7 +842,8 @@ is used instead.  */)
 DEFUN ("print", Fprint, Sprint, 1, 2, 0,
        doc: /* Output the printed representation of OBJECT, with newlines around it.
 Quoting characters are printed when needed to make output that `read'
 DEFUN ("print", Fprint, Sprint, 1, 2, 0,
        doc: /* Output the printed representation of OBJECT, with newlines around it.
 Quoting characters are printed when needed to make output that `read'
-can handle, whenever this is possible.
+can handle, whenever this is possible.  For complex objects, the behavior
+is controlled by `print-level' and `print-length', which see.
 
 OBJECT is any of the Lisp data types: a number, a string, a symbol,
 a list, a buffer, a window, a frame, etc.
 
 OBJECT is any of the Lisp data types: a number, a string, a symbol,
 a list, a buffer, a window, a frame, etc.
@@ -889,6 +913,49 @@ to make it write to the debugging output.  */)
   return character;
 }
 
   return character;
 }
 
+
+#if defined(GNU_LINUX)
+
+/* This functionality is not vitally important in general, so we rely on
+   non-portable ability to use stderr as lvalue.  */
+
+#define WITH_REDIRECT_DEBUGGING_OUTPUT 1
+
+FILE *initial_stderr_stream = NULL;
+
+DEFUN ("redirect-debugging-output", Fredirect_debugging_output, Sredirect_debugging_output,
+       1, 2,
+       "FDebug output file: \nP",
+       doc: /* Redirect debugging output (stderr stream) to file FILE.
+If FILE is nil, reset target to the initial stderr stream.
+Optional arg APPEND non-nil (interactively, with prefix arg) means
+append to existing target file.  */)
+     (file, append)
+     Lisp_Object file, append;
+{
+  if (initial_stderr_stream != NULL)
+    fclose(stderr);
+  stderr = initial_stderr_stream;
+  initial_stderr_stream = NULL;
+
+  if (STRINGP (file))
+    {
+      file = Fexpand_file_name (file, Qnil);
+      initial_stderr_stream = stderr;
+      stderr = fopen(SDATA (file), NILP (append) ? "w" : "a");
+      if (stderr == NULL)
+       {
+         stderr = initial_stderr_stream;
+         initial_stderr_stream = NULL;
+         report_file_error ("Cannot open debugging output stream",
+                            Fcons (file, Qnil));
+       }
+    }
+  return Qnil;
+}
+#endif /* GNU_LINUX */
+
+
 /* This is the interface for debugging printing.  */
 
 void
 /* This is the interface for debugging printing.  */
 
 void
@@ -901,7 +968,9 @@ debug_print (arg)
 \f
 DEFUN ("error-message-string", Ferror_message_string, Serror_message_string,
        1, 1, 0,
 \f
 DEFUN ("error-message-string", Ferror_message_string, Serror_message_string,
        1, 1, 0,
-       doc: /* Convert an error value (ERROR-SYMBOL . DATA) to an error message.  */)
+       doc: /* Convert an error value (ERROR-SYMBOL . DATA) to an error message.
+See Info anchor `(elisp)Definition of signal' for some details on how this
+error message is constructed.  */)
      (obj)
      Lisp_Object obj;
 {
      (obj)
      Lisp_Object obj;
 {
@@ -918,7 +987,7 @@ DEFUN ("error-message-string", Ferror_message_string, Serror_message_string,
       && NILP (XCDR (XCDR (obj))))
     return XCAR (XCDR (obj));
 
       && NILP (XCDR (XCDR (obj))))
     return XCAR (XCDR (obj));
 
-  print_error_message (obj, Vprin1_to_string_buffer);
+  print_error_message (obj, Vprin1_to_string_buffer, 0, Qnil);
 
   set_buffer_internal (XBUFFER (Vprin1_to_string_buffer));
   value = Fbuffer_string ();
 
   set_buffer_internal (XBUFFER (Vprin1_to_string_buffer));
   value = Fbuffer_string ();
@@ -935,13 +1004,27 @@ DEFUN ("error-message-string", Ferror_message_string, Serror_message_string,
    STREAM (suitable for the print functions).  */
 
 void
    STREAM (suitable for the print functions).  */
 
 void
-print_error_message (data, stream)
+print_error_message (data, stream, context, caller)
      Lisp_Object data, stream;
      Lisp_Object data, stream;
+     char *context;
+     Lisp_Object caller;
 {
   Lisp_Object errname, errmsg, file_error, tail;
   struct gcpro gcpro1;
   int i;
 
 {
   Lisp_Object errname, errmsg, file_error, tail;
   struct gcpro gcpro1;
   int i;
 
+  if (context != 0)
+    write_string_1 (context, -1, stream);
+
+  /* If we know from where the error was signaled, show it in
+   *Messages*.  */
+  if (!NILP (caller) && SYMBOLP (caller))
+    {
+      const char *name = SDATA (SYMBOL_NAME (caller));
+      message_dolog (name, strlen (name), 0, 0);
+      message_dolog (": ", 2, 0, 0);
+    }
+
   errname = Fcar (data);
 
   if (EQ (errname, Qerror))
   errname = Fcar (data);
 
   if (EQ (errname, Qerror))
@@ -965,16 +1048,6 @@ print_error_message (data, stream)
   tail = Fcdr_safe (data);
   GCPRO1 (tail);
 
   tail = Fcdr_safe (data);
   GCPRO1 (tail);
 
-  /* If we know from where the error was signaled, show it in
-     *Messages*.  */
-  if (!NILP (Vsignaling_function) && SYMBOLP (Vsignaling_function))
-    {
-      char *name = XSYMBOL (Vsignaling_function)->name->data;
-      message_dolog (name, strlen (name), 0, 0);
-      message_dolog (": ", 2, 0, 0);
-      Vsignaling_function = Qnil;
-    }
-
   /* For file-error, make error message by concatenating
      all the data items.  They are all strings.  */
   if (!NILP (file_error) && CONSP (tail))
   /* For file-error, make error message by concatenating
      all the data items.  They are all strings.  */
   if (!NILP (file_error) && CONSP (tail))
@@ -996,7 +1069,7 @@ print_error_message (data, stream)
       else
        Fprin1 (obj, stream);
     }
       else
        Fprin1 (obj, stream);
     }
-  
+
   UNGCPRO;
 }
 
   UNGCPRO;
 }
 
@@ -1007,9 +1080,9 @@ print_error_message (data, stream)
  * largest float, printed in the biggest notation.  This is undoubtedly
  * 20d float_output_format, with the negative of the C-constant "HUGE"
  * from <math.h>.
  * largest float, printed in the biggest notation.  This is undoubtedly
  * 20d float_output_format, with the negative of the C-constant "HUGE"
  * from <math.h>.
- * 
+ *
  * On the vax the worst case is -1e38 in 20d format which takes 61 bytes.
  * On the vax the worst case is -1e38 in 20d format which takes 61 bytes.
- * 
+ *
  * I assume that IEEE-754 format numbers can take 329 bytes for the worst
  * case of -1e307 in 20d float_output_format. What is one to do (short of
  * re-writing _doprnt to be more sane)?
  * I assume that IEEE-754 format numbers can take 329 bytes for the worst
  * case of -1e307 in 20d float_output_format. What is one to do (short of
  * re-writing _doprnt to be more sane)?
@@ -1023,7 +1096,7 @@ float_to_string (buf, data)
 {
   unsigned char *cp;
   int width;
 {
   unsigned char *cp;
   int width;
-      
+
   /* Check for plus infinity in a way that won't lose
      if there is no plus infinity.  */
   if (data == data / 2 && data > 1.0)
   /* Check for plus infinity in a way that won't lose
      if there is no plus infinity.  */
   if (data == data / 2 && data > 1.0)
@@ -1052,7 +1125,7 @@ float_to_string (buf, data)
            *buf++ = '-';
            break;
          }
            *buf++ = '-';
            break;
          }
-      
+
       strcpy (buf, "0.0e+NaN");
       return;
     }
       strcpy (buf, "0.0e+NaN");
       return;
     }
@@ -1082,7 +1155,7 @@ float_to_string (buf, data)
       /* Check that the spec we have is fully valid.
         This means not only valid for printf,
         but meant for floats, and reasonable.  */
       /* Check that the spec we have is fully valid.
         This means not only valid for printf,
         but meant for floats, and reasonable.  */
-      cp = XSTRING (Vfloat_output_format)->data;
+      cp = SDATA (Vfloat_output_format);
 
       if (cp[0] != '%')
        goto lose;
 
       if (cp[0] != '%')
        goto lose;
@@ -1112,7 +1185,7 @@ float_to_string (buf, data)
       if (cp[1] != 0)
        goto lose;
 
       if (cp[1] != 0)
        goto lose;
 
-      sprintf (buf, XSTRING (Vfloat_output_format)->data, data);
+      sprintf (buf, SDATA (Vfloat_output_format), data);
     }
 
   /* Make sure there is a decimal point with digit after, or an
     }
 
   /* Make sure there is a decimal point with digit after, or an
@@ -1147,7 +1220,7 @@ print (obj, printcharfun, escapeflag)
      register Lisp_Object printcharfun;
      int escapeflag;
 {
      register Lisp_Object printcharfun;
      int escapeflag;
 {
-  print_depth = 0;
+  old_backquote_output = 0;
 
   /* Reset print_number_index and Vprint_number_table only when
      the variable Vprint_continuous_numbering is nil.  Otherwise,
 
   /* Reset print_number_index and Vprint_number_table only when
      the variable Vprint_continuous_numbering is nil.  Otherwise,
@@ -1163,24 +1236,35 @@ print (obj, printcharfun, escapeflag)
   if (!NILP (Vprint_gensym) || !NILP (Vprint_circle))
     {
       int i, start, index;
   if (!NILP (Vprint_gensym) || !NILP (Vprint_circle))
     {
       int i, start, index;
-      /* Construct Vprint_number_table.  */
       start = index = print_number_index;
       start = index = print_number_index;
+      /* Construct Vprint_number_table.
+        This increments print_number_index for the objects added.  */
+      print_depth = 0;
       print_preprocess (obj);
       print_preprocess (obj);
+
       /* Remove unnecessary objects, which appear only once in OBJ;
       /* Remove unnecessary objects, which appear only once in OBJ;
-        that is, whose status is Qnil.  */
+        that is, whose status is Qnil.  Compactify the necessary objects.  */
       for (i = start; i < print_number_index; i++)
        if (!NILP (PRINT_NUMBER_STATUS (Vprint_number_table, i)))
          {
            PRINT_NUMBER_OBJECT (Vprint_number_table, index)
              = PRINT_NUMBER_OBJECT (Vprint_number_table, i);
       for (i = start; i < print_number_index; i++)
        if (!NILP (PRINT_NUMBER_STATUS (Vprint_number_table, i)))
          {
            PRINT_NUMBER_OBJECT (Vprint_number_table, index)
              = PRINT_NUMBER_OBJECT (Vprint_number_table, i);
-           /* Reset the status field for the next print step.  Now this
-              field means whether the object has already been printed.  */
-           PRINT_NUMBER_STATUS (Vprint_number_table, index) = Qnil;
            index++;
          }
            index++;
          }
+
+      /* Clear out objects outside the active part of the table.  */
+      for (i = index; i < print_number_index; i++)
+       PRINT_NUMBER_OBJECT (Vprint_number_table, i) = Qnil;
+
+      /* Reset the status field for the next print step.  Now this
+        field means whether the object has already been printed.  */
+      for (i = start; i < print_number_index; i++)
+       PRINT_NUMBER_STATUS (Vprint_number_table, i) = Qnil;
+
       print_number_index = index;
     }
 
       print_number_index = index;
     }
 
+  print_depth = 0;
   print_object (obj, printcharfun, escapeflag);
 }
 
   print_object (obj, printcharfun, escapeflag);
 }
 
@@ -1195,7 +1279,28 @@ static void
 print_preprocess (obj)
      Lisp_Object obj;
 {
 print_preprocess (obj)
      Lisp_Object obj;
 {
-  int i, size;
+  int i;
+  EMACS_INT size;
+  int loop_count = 0;
+  Lisp_Object halftail;
+
+  /* Give up if we go so deep that print_object will get an error.  */
+  /* See similar code in print_object.  */
+  if (print_depth >= PRINT_CIRCLE)
+    return;
+
+  /* Avoid infinite recursion for circular nested structure
+     in the case where Vprint_circle is nil.  */
+  if (NILP (Vprint_circle))
+    {
+      for (i = 0; i < print_depth; i++)
+       if (EQ (obj, being_printed[i]))
+         return;
+      being_printed[print_depth] = obj;
+    }
+
+  print_depth++;
+  halftail = obj;
 
  loop:
   if (STRINGP (obj) || CONSP (obj) || VECTORP (obj)
 
  loop:
   if (STRINGP (obj) || CONSP (obj) || VECTORP (obj)
@@ -1251,17 +1356,26 @@ print_preprocess (obj)
        {
        case Lisp_String:
          /* A string may have text properties, which can be circular.  */
        {
        case Lisp_String:
          /* A string may have text properties, which can be circular.  */
-         traverse_intervals_noorder (XSTRING (obj)->intervals,
+         traverse_intervals_noorder (STRING_INTERVALS (obj),
                                      print_preprocess_string, Qnil);
          break;
 
        case Lisp_Cons:
                                      print_preprocess_string, Qnil);
          break;
 
        case Lisp_Cons:
+         /* Use HALFTAIL and LOOP_COUNT to detect circular lists,
+            just as in print_object.  */
+         if (loop_count && EQ (obj, halftail))
+           break;
          print_preprocess (XCAR (obj));
          obj = XCDR (obj);
          print_preprocess (XCAR (obj));
          obj = XCDR (obj);
+         loop_count++;
+         if (!(loop_count & 1))
+           halftail = XCDR (halftail);
          goto loop;
 
        case Lisp_Vectorlike:
          goto loop;
 
        case Lisp_Vectorlike:
-         size = XVECTOR (obj)->size & PSEUDOVECTOR_SIZE_MASK;
+         size = XVECTOR (obj)->size;
+         if (size & PSEUDOVECTOR_FLAG)
+           size &= PSEUDOVECTOR_SIZE_MASK;
          for (i = 0; i < size; i++)
            print_preprocess (XVECTOR (obj)->contents[i]);
          break;
          for (i = 0; i < size; i++)
            print_preprocess (XVECTOR (obj)->contents[i]);
          break;
@@ -1270,6 +1384,7 @@ print_preprocess (obj)
          break;
        }
     }
          break;
        }
     }
+  print_depth--;
 }
 
 static void
 }
 
 static void
@@ -1286,7 +1401,7 @@ print_object (obj, printcharfun, escapeflag)
      register Lisp_Object printcharfun;
      int escapeflag;
 {
      register Lisp_Object printcharfun;
      int escapeflag;
 {
-  char buf[30];
+  char buf[40];
 
   QUIT;
 
 
   QUIT;
 
@@ -1340,6 +1455,7 @@ print_object (obj, printcharfun, escapeflag)
 
   print_depth++;
 
 
   print_depth++;
 
+  /* See similar code in print_preprocess.  */
   if (print_depth > PRINT_CIRCLE)
     error ("Apparently circular structure being printed");
 #ifdef MAX_PRINT_CHARS
   if (print_depth > PRINT_CIRCLE)
     error ("Apparently circular structure being printed");
 #ifdef MAX_PRINT_CHARS
@@ -1383,18 +1499,19 @@ print_object (obj, printcharfun, escapeflag)
          /* 1 means we must ensure that the next character we output
             cannot be taken as part of a hex character escape.  */
          int need_nonhex = 0;
          /* 1 means we must ensure that the next character we output
             cannot be taken as part of a hex character escape.  */
          int need_nonhex = 0;
+         int multibyte = STRING_MULTIBYTE (obj);
 
          GCPRO1 (obj);
 
 
          GCPRO1 (obj);
 
-         if (!NULL_INTERVAL_P (XSTRING (obj)->intervals))
+         if (!NULL_INTERVAL_P (STRING_INTERVALS (obj)))
            {
              PRINTCHAR ('#');
              PRINTCHAR ('(');
            }
 
          PRINTCHAR ('\"');
            {
              PRINTCHAR ('#');
              PRINTCHAR ('(');
            }
 
          PRINTCHAR ('\"');
-         str = XSTRING (obj)->data;
-         size_byte = STRING_BYTES (XSTRING (obj));
+         str = SDATA (obj);
+         size_byte = SBYTES (obj);
 
          for (i = 0, i_byte = 0; i_byte < size_byte;)
            {
 
          for (i = 0, i_byte = 0; i_byte < size_byte;)
            {
@@ -1403,7 +1520,7 @@ print_object (obj, printcharfun, escapeflag)
              int len;
              int c;
 
              int len;
              int c;
 
-             if (STRING_MULTIBYTE (obj))
+             if (multibyte)
                {
                  c = STRING_CHAR_AND_LENGTH (str + i_byte,
                                              size_byte - i_byte, len);
                {
                  c = STRING_CHAR_AND_LENGTH (str + i_byte,
                                              size_byte - i_byte, len);
@@ -1427,16 +1544,22 @@ print_object (obj, printcharfun, escapeflag)
                  PRINTCHAR ('\\');
                  PRINTCHAR ('f');
                }
                  PRINTCHAR ('\\');
                  PRINTCHAR ('f');
                }
-             else if (! SINGLE_BYTE_CHAR_P (c) && print_escape_multibyte)
+             else if (multibyte
+                      && ! ASCII_BYTE_P (c)
+                      && (SINGLE_BYTE_CHAR_P (c) || print_escape_multibyte))
                {
                  /* When multibyte is disabled,
                {
                  /* When multibyte is disabled,
-                    print multibyte string chars using hex escapes.  */
+                    print multibyte string chars using hex escapes.
+                    For a char code that could be in a unibyte string,
+                    when found in a multibyte string, always use a hex escape
+                    so it reads back as multibyte.  */
                  unsigned char outbuf[50];
                  sprintf (outbuf, "\\x%x", c);
                  strout (outbuf, -1, -1, printcharfun, 0);
                  need_nonhex = 1;
                }
                  unsigned char outbuf[50];
                  sprintf (outbuf, "\\x%x", c);
                  strout (outbuf, -1, -1, printcharfun, 0);
                  need_nonhex = 1;
                }
-             else if (SINGLE_BYTE_CHAR_P (c) && ! ASCII_BYTE_P (c)
+             else if (! multibyte
+                      && SINGLE_BYTE_CHAR_P (c) && ! ASCII_BYTE_P (c)
                       && print_escape_nonascii)
                {
                  /* When printing in a multibyte buffer
                       && print_escape_nonascii)
                {
                  /* When printing in a multibyte buffer
@@ -1468,9 +1591,9 @@ print_object (obj, printcharfun, escapeflag)
            }
          PRINTCHAR ('\"');
 
            }
          PRINTCHAR ('\"');
 
-         if (!NULL_INTERVAL_P (XSTRING (obj)->intervals))
+         if (!NULL_INTERVAL_P (STRING_INTERVALS (obj)))
            {
            {
-             traverse_intervals (XSTRING (obj)->intervals,
+             traverse_intervals (STRING_INTERVALS (obj),
                                  0, print_interval, printcharfun);
              PRINTCHAR (')');
            }
                                  0, print_interval, printcharfun);
              PRINTCHAR (')');
            }
@@ -1482,13 +1605,13 @@ print_object (obj, printcharfun, escapeflag)
     case Lisp_Symbol:
       {
        register int confusing;
     case Lisp_Symbol:
       {
        register int confusing;
-       register unsigned char *p = XSYMBOL (obj)->name->data;
-       register unsigned char *end = p + STRING_BYTES (XSYMBOL (obj)->name);
+       register unsigned char *p = SDATA (SYMBOL_NAME (obj));
+       register unsigned char *end = p + SBYTES (SYMBOL_NAME (obj));
        register int c;
        int i, i_byte, size_byte;
        Lisp_Object name;
 
        register int c;
        int i, i_byte, size_byte;
        Lisp_Object name;
 
-       XSETSTRING (name, XSYMBOL (obj)->name);
+       name = SYMBOL_NAME (obj);
 
        if (p != end && (*p == '-' || *p == '+')) p++;
        if (p == end)
 
        if (p != end && (*p == '-' || *p == '+')) p++;
        if (p == end)
@@ -1518,7 +1641,7 @@ print_object (obj, printcharfun, escapeflag)
            PRINTCHAR (':');
          }
 
            PRINTCHAR (':');
          }
 
-       size_byte = STRING_BYTES (XSTRING (name));
+       size_byte = SBYTES (name);
 
        for (i = 0, i_byte = 0; i_byte < size_byte;)
          {
 
        for (i = 0, i_byte = 0; i_byte < size_byte;)
          {
@@ -1560,6 +1683,7 @@ print_object (obj, printcharfun, escapeflag)
          print_object (XCAR (XCDR (obj)), printcharfun, escapeflag);
        }
       else if (print_quoted && CONSP (XCDR (obj)) && NILP (XCDR (XCDR (obj)))
          print_object (XCAR (XCDR (obj)), printcharfun, escapeflag);
        }
       else if (print_quoted && CONSP (XCDR (obj)) && NILP (XCDR (XCDR (obj)))
+              && ! old_backquote_output
               && ((EQ (XCAR (obj), Qbackquote)
                    || EQ (XCAR (obj), Qcomma)
                    || EQ (XCAR (obj), Qcomma_at)
               && ((EQ (XCAR (obj), Qbackquote)
                    || EQ (XCAR (obj), Qcomma)
                    || EQ (XCAR (obj), Qcomma_at)
@@ -1571,6 +1695,29 @@ print_object (obj, printcharfun, escapeflag)
       else
        {
          PRINTCHAR ('(');
       else
        {
          PRINTCHAR ('(');
+
+         /* If the first element is a backquote form,
+            print it old-style so it won't be misunderstood.  */
+         if (print_quoted && CONSP (XCAR (obj))
+             && CONSP (XCDR (XCAR (obj)))
+             && NILP (XCDR (XCDR (XCAR (obj))))
+             && EQ (XCAR (XCAR (obj)), Qbackquote))
+           {
+             Lisp_Object tem;
+             tem = XCAR (obj);
+             PRINTCHAR ('(');
+
+             print_object (Qbackquote, printcharfun, 0);
+             PRINTCHAR (' ');
+
+             ++old_backquote_output;
+             print_object (XCAR (XCDR (tem)), printcharfun, 0);
+             --old_backquote_output;
+             PRINTCHAR (')');
+
+             obj = XCDR (obj);
+           }
+
          {
            int print_length, i;
            Lisp_Object halftail = obj;
          {
            int print_length, i;
            Lisp_Object halftail = obj;
@@ -1620,18 +1767,18 @@ print_object (obj, printcharfun, escapeflag)
                            }
                      }
                  }
                            }
                      }
                  }
-               
+
                if (i++)
                  PRINTCHAR (' ');
                if (i++)
                  PRINTCHAR (' ');
-               
+
                if (print_length && i > print_length)
                  {
                    strout ("...", 3, 3, printcharfun, 0);
                    goto end_of_list;
                  }
                if (print_length && i > print_length)
                  {
                    strout ("...", 3, 3, printcharfun, 0);
                    goto end_of_list;
                  }
-               
+
                print_object (XCAR (obj), printcharfun, escapeflag);
                print_object (XCAR (obj), printcharfun, escapeflag);
-               
+
                obj = XCDR (obj);
                if (!(i & 1))
                  halftail = XCDR (halftail);
                obj = XCDR (obj);
                if (!(i & 1))
                  halftail = XCDR (halftail);
@@ -1644,7 +1791,7 @@ print_object (obj, printcharfun, escapeflag)
              strout (" . ", 3, 3, printcharfun, 0);
              print_object (obj, printcharfun, escapeflag);
            }
              strout (" . ", 3, 3, printcharfun, 0);
              print_object (obj, printcharfun, escapeflag);
            }
-         
+
        end_of_list:
          PRINTCHAR (')');
        }
        end_of_list:
          PRINTCHAR (')');
        }
@@ -1668,13 +1815,14 @@ print_object (obj, printcharfun, escapeflag)
          register unsigned char c;
          struct gcpro gcpro1;
          int size_in_chars
          register unsigned char c;
          struct gcpro gcpro1;
          int size_in_chars
-           = (XBOOL_VECTOR (obj)->size + BITS_PER_CHAR - 1) / BITS_PER_CHAR;
+           = ((XBOOL_VECTOR (obj)->size + BOOL_VECTOR_BITS_PER_CHAR - 1)
+              / BOOL_VECTOR_BITS_PER_CHAR);
 
          GCPRO1 (obj);
 
          PRINTCHAR ('#');
          PRINTCHAR ('&');
 
          GCPRO1 (obj);
 
          PRINTCHAR ('#');
          PRINTCHAR ('&');
-         sprintf (buf, "%d", XBOOL_VECTOR (obj)->size);
+         sprintf (buf, "%ld", (long) XBOOL_VECTOR (obj)->size);
          strout (buf, -1, -1, printcharfun, 0);
          PRINTCHAR ('\"');
 
          strout (buf, -1, -1, printcharfun, 0);
          PRINTCHAR ('\"');
 
@@ -1699,6 +1847,14 @@ print_object (obj, printcharfun, escapeflag)
                  PRINTCHAR ('\\');
                  PRINTCHAR ('f');
                }
                  PRINTCHAR ('\\');
                  PRINTCHAR ('f');
                }
+             else if (c > '\177')
+               {
+                 /* Use octal escapes to avoid encoding issues.  */
+                 PRINTCHAR ('\\');
+                 PRINTCHAR ('0' + ((c >> 6) & 3));
+                 PRINTCHAR ('0' + ((c >> 3) & 7));
+                 PRINTCHAR ('0' + (c & 7));
+               }
              else
                {
                  if (c == '\"' || c == '\\')
              else
                {
                  if (c == '\"' || c == '\\')
@@ -1719,7 +1875,7 @@ print_object (obj, printcharfun, escapeflag)
       else if (WINDOWP (obj))
        {
          strout ("#<window ", -1, -1, printcharfun, 0);
       else if (WINDOWP (obj))
        {
          strout ("#<window ", -1, -1, printcharfun, 0);
-         sprintf (buf, "%d", XFASTINT (XWINDOW (obj)->sequence_number));
+         sprintf (buf, "%ld", (long) XFASTINT (XWINDOW (obj)->sequence_number));
          strout (buf, -1, -1, printcharfun, 0);
          if (!NILP (XWINDOW (obj)->buffer))
            {
          strout (buf, -1, -1, printcharfun, 0);
          if (!NILP (XWINDOW (obj)->buffer))
            {
@@ -1736,12 +1892,12 @@ print_object (obj, printcharfun, escapeflag)
            {
              PRINTCHAR (' ');
              PRINTCHAR ('\'');
            {
              PRINTCHAR (' ');
              PRINTCHAR ('\'');
-             strout (XSYMBOL (h->test)->name->data, -1, -1, printcharfun, 0);
+             strout (SDATA (SYMBOL_NAME (h->test)), -1, -1, printcharfun, 0);
              PRINTCHAR (' ');
              PRINTCHAR (' ');
-             strout (XSYMBOL (h->weak)->name->data, -1, -1, printcharfun, 0);
+             strout (SDATA (SYMBOL_NAME (h->weak)), -1, -1, printcharfun, 0);
              PRINTCHAR (' ');
              PRINTCHAR (' ');
-             sprintf (buf, "%d/%d", XFASTINT (h->count),
-                      XVECTOR (h->next)->size);
+             sprintf (buf, "%ld/%ld", (long) XFASTINT (h->count),
+                      (long) XVECTOR (h->next)->size);
              strout (buf, -1, -1, printcharfun, 0);
            }
          sprintf (buf, " 0x%lx", (unsigned long) h);
              strout (buf, -1, -1, printcharfun, 0);
            }
          sprintf (buf, " 0x%lx", (unsigned long) h);
@@ -1771,13 +1927,13 @@ print_object (obj, printcharfun, escapeflag)
                   ? "#<frame " : "#<dead frame "),
                  -1, -1, printcharfun, 0);
          print_string (XFRAME (obj)->name, printcharfun);
                   ? "#<frame " : "#<dead frame "),
                  -1, -1, printcharfun, 0);
          print_string (XFRAME (obj)->name, printcharfun);
-         sprintf (buf, " 0x%lx\\ ", (unsigned long) (XFRAME (obj)));
+         sprintf (buf, " 0x%lx", (unsigned long) (XFRAME (obj)));
          strout (buf, -1, -1, printcharfun, 0);
          PRINTCHAR ('>');
        }
       else
        {
          strout (buf, -1, -1, printcharfun, 0);
          PRINTCHAR ('>');
        }
       else
        {
-         int size = XVECTOR (obj)->size;
+         EMACS_INT size = XVECTOR (obj)->size;
          if (COMPILEDP (obj))
            {
              PRINTCHAR ('#');
          if (COMPILEDP (obj))
            {
              PRINTCHAR ('#');
@@ -1864,7 +2020,7 @@ print_object (obj, printcharfun, escapeflag)
          break;
 
        case Lisp_Misc_Intfwd:
          break;
 
        case Lisp_Misc_Intfwd:
-         sprintf (buf, "#<intfwd to %d>", *XINTFWD (obj)->intvar);
+         sprintf (buf, "#<intfwd to %ld>", (long) *XINTFWD (obj)->intvar);
          strout (buf, -1, -1, printcharfun, 0);
          break;
 
          strout (buf, -1, -1, printcharfun, 0);
          break;
 
@@ -2028,7 +2184,9 @@ Also print formfeeds as `\\f'.  */);
   DEFVAR_BOOL ("print-escape-nonascii", &print_escape_nonascii,
               doc: /* Non-nil means print unibyte non-ASCII chars in strings as \\OOO.
 \(OOO is the octal representation of the character code.)
   DEFVAR_BOOL ("print-escape-nonascii", &print_escape_nonascii,
               doc: /* Non-nil means print unibyte non-ASCII chars in strings as \\OOO.
 \(OOO is the octal representation of the character code.)
-Only single-byte characters are affected, and only in `prin1'.  */);
+Only single-byte characters are affected, and only in `prin1'.
+When the output goes in a multibyte buffer, this feature is
+enabled regardless of the value of the variable.  */);
   print_escape_nonascii = 0;
 
   DEFVAR_BOOL ("print-escape-multibyte", &print_escape_multibyte,
   print_escape_nonascii = 0;
 
   DEFVAR_BOOL ("print-escape-multibyte", &print_escape_multibyte,
@@ -2074,10 +2232,14 @@ This variable should not be set with `setq'; bind it with a `let' instead.  */);
   DEFVAR_LISP ("print-number-table", &Vprint_number_table,
               doc: /* A vector used internally to produce `#N=' labels and `#N#' references.
 The Lisp printer uses this vector to detect Lisp objects referenced more
   DEFVAR_LISP ("print-number-table", &Vprint_number_table,
               doc: /* A vector used internally to produce `#N=' labels and `#N#' references.
 The Lisp printer uses this vector to detect Lisp objects referenced more
-than once.  When `print-continuous-numbering' is bound to t, you should
-probably also bind `print-number-table' to nil.  This ensures that the
-value of `print-number-table' can be garbage-collected once the printing
-is done.  */);
+than once.
+
+When you bind `print-continuous-numbering' to t, you should probably
+also bind `print-number-table' to nil.  This ensures that the value of
+`print-number-table' can be garbage-collected once the printing is
+done.  If all elements of `print-number-table' are nil, it means that
+the printing done so far has not found any shared structure or objects
+that need to be recorded in the table.  */);
   Vprint_number_table = Qnil;
 
   /* prin1_to_string_buffer initialized in init_buffer_once in buffer.c */
   Vprint_number_table = Qnil;
 
   /* prin1_to_string_buffer initialized in init_buffer_once in buffer.c */
@@ -2091,6 +2253,9 @@ is done.  */);
   defsubr (&Sterpri);
   defsubr (&Swrite_char);
   defsubr (&Sexternal_debugging_output);
   defsubr (&Sterpri);
   defsubr (&Swrite_char);
   defsubr (&Sexternal_debugging_output);
+#ifdef WITH_REDIRECT_DEBUGGING_OUTPUT
+  defsubr (&Sredirect_debugging_output);
+#endif
 
   Qexternal_debugging_output = intern ("external-debugging-output");
   staticpro (&Qexternal_debugging_output);
 
   Qexternal_debugging_output = intern ("external-debugging-output");
   staticpro (&Qexternal_debugging_output);
@@ -2106,3 +2271,6 @@ is done.  */);
 
   defsubr (&Swith_output_to_temp_buffer);
 }
 
   defsubr (&Swith_output_to_temp_buffer);
 }
+
+/* arch-tag: bc797170-94ae-41de-86e3-75e20f8f7a39
+   (do not change this comment) */