Merge from trunk
[bpt/emacs.git] / src / print.c
index 91ac68c..602575b 100644 (file)
@@ -1,7 +1,7 @@
 /* Lisp object printing and output streams.
-   Copyright (C) 1985, 1986, 1988, 1993, 1994, 1995, 1997,
-                 1998, 1999, 2000, 2001, 2002, 2003, 2004,
-                 2005, 2006, 2007, 2008, 2009, 2010 Free Software Foundation, Inc.
+
+Copyright (C) 1985-1986, 1988, 1993-1995, 1997-2011
+  Free Software Foundation, Inc.
 
 This file is part of GNU Emacs.
 
@@ -37,49 +37,25 @@ along with GNU Emacs.  If not, see <http://www.gnu.org/licenses/>.  */
 #include "termhooks.h"         /* For struct terminal.  */
 #include "font.h"
 
-Lisp_Object Vstandard_output, Qstandard_output;
+Lisp_Object Qstandard_output;
 
 Lisp_Object Qtemp_buffer_setup_hook;
 
 /* These are used to print like we read.  */
 
-Lisp_Object Vfloat_output_format, Qfloat_output_format;
+Lisp_Object Qfloat_output_format;
 
 #include <math.h>
 
 #if STDC_HEADERS
 #include <float.h>
 #endif
+#include <ftoastr.h>
 
 /* Default to values appropriate for IEEE floating point.  */
-#ifndef FLT_RADIX
-#define FLT_RADIX 2
-#endif
-#ifndef DBL_MANT_DIG
-#define DBL_MANT_DIG 53
-#endif
 #ifndef DBL_DIG
 #define DBL_DIG 15
 #endif
-#ifndef DBL_MIN
-#define DBL_MIN 2.2250738585072014e-308
-#endif
-
-#ifdef DBL_MIN_REPLACEMENT
-#undef DBL_MIN
-#define DBL_MIN DBL_MIN_REPLACEMENT
-#endif
-
-/* Define DOUBLE_DIGITS_BOUND, an upper bound on the number of decimal digits
-   needed to express a float without losing information.
-   The general-case formula is valid for the usual case, IEEE floating point,
-   but many compilers can't optimize the formula to an integer constant,
-   so make a special case for it.  */
-#if FLT_RADIX == 2 && DBL_MANT_DIG == 53
-#define DOUBLE_DIGITS_BOUND 17 /* IEEE floating point */
-#else
-#define DOUBLE_DIGITS_BOUND ((int) ceil (log10 (pow (FLT_RADIX, DBL_MANT_DIG))))
-#endif
 
 /* Avoid actual stack overflow in print.  */
 int print_depth;
@@ -96,74 +72,28 @@ Lisp_Object being_printed[PRINT_CIRCLE];
 char *print_buffer;
 
 /* Size allocated in print_buffer.  */
-int print_buffer_size;
+EMACS_INT print_buffer_size;
 /* Chars stored in print_buffer.  */
-int print_buffer_pos;
+EMACS_INT print_buffer_pos;
 /* Bytes stored in print_buffer.  */
-int print_buffer_pos_byte;
-
-/* Maximum length of list to print in full; noninteger means
-   effectively infinity */
-
-Lisp_Object Vprint_length;
-
-/* Maximum depth of list to print in full; noninteger means
-   effectively infinity.  */
-
-Lisp_Object Vprint_level;
-
-/* Nonzero means print newlines in strings as \n.  */
-
-int print_escape_newlines;
-
-/* Nonzero means to print single-byte non-ascii characters in strings as
-   octal escapes.  */
-
-int print_escape_nonascii;
-
-/* Nonzero means to print multibyte characters in strings as hex escapes.  */
-
-int print_escape_multibyte;
+EMACS_INT print_buffer_pos_byte;
 
 Lisp_Object Qprint_escape_newlines;
 Lisp_Object Qprint_escape_multibyte, Qprint_escape_nonascii;
 
-/* Nonzero means print (quote foo) forms as 'foo, etc.  */
-
-int print_quoted;
-
-/* Non-nil means print #: before uninterned symbols.  */
-
-Lisp_Object Vprint_gensym;
-
-/* Non-nil means print recursive structures using #n= and #n# syntax.  */
-
-Lisp_Object Vprint_circle;
-
-/* Non-nil means keep continuous number for #n= and #n# syntax
-   between several print functions.  */
-
-Lisp_Object Vprint_continuous_numbering;
-
-/* Vprint_number_table is a vector like [OBJ1 STAT1 OBJ2 STAT2 ...],
-   where OBJn are objects going to be printed, and STATn are their status,
-   which may be different meanings during process.  See the comments of
-   the functions print and print_preprocess for details.
-   print_number_index keeps the last position the next object should be added,
-   twice of which is the actual vector position in Vprint_number_table.  */
+/* Vprint_number_table is a table, that keeps objects that are going to
+   be printed, to allow use of #n= and #n# to express sharing.
+   For any given object, the table can give the following values:
+     t    the object will be printed only once.
+     -N   the object will be printed several times and will take number N.
+     N    the object has been printed so we can refer to it as #N#.
+   print_number_index holds the largest N already used.
+   N has to be striclty larger than 0 since we need to distinguish -N.  */
 int print_number_index;
-Lisp_Object Vprint_number_table;
-
-/* PRINT_NUMBER_OBJECT returns the I'th object in Vprint_number_table TABLE.
-   PRINT_NUMBER_STATUS returns the status of the I'th object in TABLE.
-   See the comment of the variable Vprint_number_table.  */
-#define PRINT_NUMBER_OBJECT(table,i) XVECTOR ((table))->contents[(i) * 2]
-#define PRINT_NUMBER_STATUS(table,i) XVECTOR ((table))->contents[(i) * 2 + 1]
-
 void print_interval (INTERVAL interval, Lisp_Object printcharfun);
 
 /* GDB resets this to zero on W32 to disable OutputDebugString calls.  */
-int print_output_debug_flag = 1;
+int print_output_debug_flag EXTERNALLY_VISIBLE = 1;
 
 \f
 /* Low level output routines for characters and strings */
@@ -177,11 +107,11 @@ int print_output_debug_flag = 1;
 
 #define PRINTDECLARE                                                   \
    struct buffer *old = current_buffer;                                        \
-   int old_point = -1, start_point = -1;                               \
-   int old_point_byte = -1, start_point_byte = -1;                     \
+   EMACS_INT old_point = -1, start_point = -1;                         \
+   EMACS_INT old_point_byte = -1, start_point_byte = -1;               \
    int specpdl_count = SPECPDL_INDEX ();                               \
    int free_print_buffer = 0;                                          \
-   int multibyte = !NILP (current_buffer->enable_multibyte_characters);        \
+   int multibyte = !NILP (BVAR (current_buffer, enable_multibyte_characters)); \
    Lisp_Object original
 
 #define PRINTPREPARE                                                   \
@@ -214,10 +144,10 @@ int print_output_debug_flag = 1;
    if (NILP (printcharfun))                                            \
      {                                                                 \
        Lisp_Object string;                                             \
-       if (NILP (current_buffer->enable_multibyte_characters)          \
+       if (NILP (BVAR (current_buffer, enable_multibyte_characters))           \
           && ! print_escape_multibyte)                                 \
          specbind (Qprint_escape_multibyte, Qt);                       \
-       if (! NILP (current_buffer->enable_multibyte_characters)                \
+       if (! NILP (BVAR (current_buffer, enable_multibyte_characters))         \
           && ! print_escape_nonascii)                                  \
          specbind (Qprint_escape_nonascii, Qt);                                \
        if (print_buffer != 0)                                          \
@@ -243,13 +173,13 @@ int print_output_debug_flag = 1;
    if (NILP (printcharfun))                                            \
      {                                                                 \
        if (print_buffer_pos != print_buffer_pos_byte                   \
-          && NILP (current_buffer->enable_multibyte_characters))       \
+          && NILP (BVAR (current_buffer, enable_multibyte_characters)))        \
         {                                                              \
           unsigned char *temp                                          \
             = (unsigned char *) alloca (print_buffer_pos + 1);         \
-          copy_text (print_buffer, temp, print_buffer_pos_byte,        \
-                     1, 0);                                            \
-          insert_1_both (temp, print_buffer_pos,                       \
+          copy_text ((unsigned char *) print_buffer, temp,             \
+                     print_buffer_pos_byte, 1, 0);                     \
+          insert_1_both ((char *) temp, print_buffer_pos,              \
                          print_buffer_pos, 0, 1, 0);                   \
         }                                                              \
        else                                                            \
@@ -320,11 +250,11 @@ printchar (unsigned int ch, Lisp_Object fun)
       else
        {
          int multibyte_p
-           = !NILP (current_buffer->enable_multibyte_characters);
+           = !NILP (BVAR (current_buffer, enable_multibyte_characters));
 
          setup_echo_area_for_printing (multibyte_p);
          insert_char (ch);
-         message_dolog (str, len, 0, multibyte_p);
+         message_dolog ((char *) str, len, 0, multibyte_p);
        }
     }
 }
@@ -342,8 +272,8 @@ printchar (unsigned int ch, Lisp_Object fun)
    to data in a Lisp string.  Otherwise that is not safe.  */
 
 static void
-strout (const char *ptr, int size, int size_byte, Lisp_Object printcharfun,
-       int multibyte)
+strout (const char *ptr, EMACS_INT size, EMACS_INT size_byte,
+       Lisp_Object printcharfun, int multibyte)
 {
   if (size < 0)
     size_byte = size = strlen (ptr);
@@ -372,7 +302,7 @@ strout (const char *ptr, int size, int size_byte, Lisp_Object printcharfun,
         job.  */
       int i;
       int multibyte_p
-       = !NILP (current_buffer->enable_multibyte_characters);
+       = !NILP (BVAR (current_buffer, enable_multibyte_characters));
 
       setup_echo_area_for_printing (multibyte_p);
       message_dolog (ptr, size_byte, 0, multibyte_p);
@@ -387,7 +317,8 @@ strout (const char *ptr, int size, int size_byte, Lisp_Object printcharfun,
          int len;
          for (i = 0; i < size_byte; i += len)
            {
-             int ch = STRING_CHAR_AND_LENGTH (ptr + i, len);
+             int ch = STRING_CHAR_AND_LENGTH ((const unsigned char *) ptr + i,
+                                              len);
              insert_char (ch);
            }
        }
@@ -395,7 +326,7 @@ strout (const char *ptr, int size, int size_byte, Lisp_Object printcharfun,
   else
     {
       /* PRINTCHARFUN is a Lisp function.  */
-      int i = 0;
+      EMACS_INT i = 0;
 
       if (size == size_byte)
        {
@@ -413,7 +344,8 @@ strout (const char *ptr, int size, int size_byte, Lisp_Object printcharfun,
                 corresponding character code before handing it to
                 PRINTCHAR.  */
              int len;
-             int ch = STRING_CHAR_AND_LENGTH (ptr + i, len);
+             int ch = STRING_CHAR_AND_LENGTH ((const unsigned char *) ptr + i,
+                                              len);
              PRINTCHAR (ch);
              i += len;
            }
@@ -430,7 +362,7 @@ print_string (Lisp_Object string, Lisp_Object printcharfun)
 {
   if (EQ (printcharfun, Qt) || NILP (printcharfun))
     {
-      int chars;
+      EMACS_INT chars;
 
       if (print_escape_nonascii)
        string = string_escape_byte8 (string);
@@ -439,14 +371,14 @@ print_string (Lisp_Object string, Lisp_Object printcharfun)
        chars = SCHARS (string);
       else if (! print_escape_nonascii
               && (EQ (printcharfun, Qt)
-                  ? ! NILP (buffer_defaults.enable_multibyte_characters)
-                  : ! NILP (current_buffer->enable_multibyte_characters)))
+                  ? ! NILP (BVAR (&buffer_defaults, enable_multibyte_characters))
+                  : ! NILP (BVAR (current_buffer, enable_multibyte_characters))))
        {
          /* If unibyte string STRING contains 8-bit codes, we must
             convert STRING to a multibyte string containing the same
             character codes.  */
          Lisp_Object newstr;
-         int bytes;
+         EMACS_INT bytes;
 
          chars = SBYTES (string);
          bytes = parse_str_to_multibyte (SDATA (string), chars);
@@ -464,7 +396,7 @@ print_string (Lisp_Object string, Lisp_Object printcharfun)
       if (EQ (printcharfun, Qt))
        {
          /* Output to echo area.  */
-         int nbytes = SBYTES (string);
+         EMACS_INT nbytes = SBYTES (string);
          char *buffer;
 
          /* Copy the string contents so that relocation of STRING by
@@ -481,7 +413,7 @@ print_string (Lisp_Object string, Lisp_Object printcharfun)
        }
       else
        /* No need to copy, since output to print_buffer can't GC.  */
-       strout (SDATA (string),
+       strout (SSDATA (string),
                chars, SBYTES (string),
                printcharfun, STRING_MULTIBYTE (string));
     }
@@ -489,9 +421,9 @@ print_string (Lisp_Object string, Lisp_Object printcharfun)
     {
       /* Otherwise, string may be relocated by printing one char.
         So re-fetch the string address for each character.  */
-      int i;
-      int size = SCHARS (string);
-      int size_byte = SBYTES (string);
+      EMACS_INT i;
+      EMACS_INT size = SCHARS (string);
+      EMACS_INT size_byte = SBYTES (string);
       struct gcpro gcpro1;
       GCPRO1 (string);
       if (size == size_byte)
@@ -544,11 +476,11 @@ write_string (const char *data, int size)
   PRINTFINISH;
 }
 
-/* Used from outside of print.c to print a block of SIZE
-   single-byte chars at DATA on a specified stream PRINTCHARFUN.
+/* Used to print a block of SIZE single-byte chars at DATA on a
+   specified stream PRINTCHARFUN.
    Do not use this on the contents of a Lisp string.  */
 
-void
+static void
 write_string_1 (const char *data, int size, Lisp_Object printcharfun)
 {
   PRINTDECLARE;
@@ -572,14 +504,14 @@ temp_output_buffer_setup (const char *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;
+  BVAR (current_buffer, directory) = BVAR (old, directory);
+  BVAR (current_buffer, read_only) = Qnil;
+  BVAR (current_buffer, filename) = Qnil;
+  BVAR (current_buffer, undo_list) = Qt;
   eassert (current_buffer->overlays_before == NULL);
   eassert (current_buffer->overlays_after == NULL);
-  current_buffer->enable_multibyte_characters
-    = buffer_defaults.enable_multibyte_characters;
+  BVAR (current_buffer, enable_multibyte_characters)
+    = BVAR (&buffer_defaults, enable_multibyte_characters);
   specbind (Qinhibit_read_only, Qt);
   specbind (Qinhibit_modification_hooks, Qt);
   Ferase_buffer ();
@@ -592,6 +524,7 @@ temp_output_buffer_setup (const char *bufname)
   specbind (Qstandard_output, buf);
 }
 
+/* FIXME: Use Lisp's with-output-to-temp-buffer instead!  */
 Lisp_Object
 internal_with_output_to_temp_buffer (const char *bufname, Lisp_Object (*function) (Lisp_Object), Lisp_Object args)
 {
@@ -613,60 +546,6 @@ internal_with_output_to_temp_buffer (const char *bufname, Lisp_Object (*function
 
   return unbind_to (count, val);
 }
-
-DEFUN ("with-output-to-temp-buffer",
-       Fwith_output_to_temp_buffer, Swith_output_to_temp_buffer,
-       1, UNEVALLED, 0,
-       doc: /* Bind `standard-output' to buffer BUFNAME, eval BODY, then show that buffer.
-
-This construct makes buffer BUFNAME empty before running BODY.
-It does not make the buffer current for BODY.
-Instead it binds `standard-output' to that buffer, so that output
-generated with `prin1' and similar functions in BODY goes into
-the buffer.
-
-At the end of BODY, this marks buffer BUFNAME unmodifed and displays
-it in a window, but does not select it.  The normal way to do this is
-by calling `display-buffer', then running `temp-buffer-show-hook'.
-However, if `temp-buffer-show-function' is non-nil, it calls that
-function instead (and does not run `temp-buffer-show-hook').  The
-function gets one argument, the buffer to display.
-
-The return value of `with-output-to-temp-buffer' is the value of the
-last form in BODY.  If BODY does not finish normally, the buffer
-BUFNAME is not displayed.
-
-This runs the hook `temp-buffer-setup-hook' before BODY,
-with the buffer BUFNAME temporarily current.  It runs the hook
-`temp-buffer-show-hook' after displaying buffer BUFNAME, with that
-buffer temporarily current, and the window that was used to display it
-temporarily selected.  But it doesn't run `temp-buffer-show-hook'
-if it uses `temp-buffer-show-function'.
-
-usage: (with-output-to-temp-buffer BUFNAME BODY...)  */)
-  (Lisp_Object args)
-{
-  struct gcpro gcpro1;
-  Lisp_Object name;
-  int count = SPECPDL_INDEX ();
-  Lisp_Object buf, val;
-
-  GCPRO1(args);
-  name = Feval (Fcar (args));
-  CHECK_STRING (name);
-  temp_output_buffer_setup (SDATA (name));
-  buf = Vstandard_output;
-  UNGCPRO;
-
-  val = Fprogn (XCDR (args));
-
-  GCPRO1 (val);
-  temp_output_buffer_show (buf);
-  UNGCPRO;
-
-  return unbind_to (count, val);
-}
-
 \f
 static void print (Lisp_Object obj, register Lisp_Object printcharfun, int escapeflag);
 static void print_preprocess (Lisp_Object obj);
@@ -868,7 +747,7 @@ to make it write to the debugging output.  */)
   (Lisp_Object character)
 {
   CHECK_NUMBER (character);
-  putc (XINT (character), stderr);
+  putc ((int) XINT (character), stderr);
 
 #ifdef WINDOWSNT
   /* Send the output to a debugger (nothing happens if there isn't one).  */
@@ -1082,12 +961,13 @@ print_error_message (Lisp_Object data, Lisp_Object stream, const char *context,
  * case of -1e307 in 20d float_output_format. What is one to do (short of
  * re-writing _doprnt to be more sane)?
  *                     -wsr
+ * Given the above, the buffer must be least FLOAT_TO_STRING_BUFSIZE bytes.
  */
 
 void
-float_to_string (unsigned char *buf, double data)
+float_to_string (char *buf, double data)
 {
-  unsigned char *cp;
+  char *cp;
   int width;
 
   /* Check for plus infinity in a way that won't lose
@@ -1128,27 +1008,18 @@ float_to_string (unsigned char *buf, double data)
   lose:
     {
       /* Generate the fewest number of digits that represent the
-        floating point value without losing information.
-        The following method is simple but a bit slow.
-        For ideas about speeding things up, please see:
-
-        Guy L Steele Jr & Jon L White, How to print floating-point numbers
-        accurately.  SIGPLAN notices 25, 6 (June 1990), 112-126.
-
-        Robert G Burger & R Kent Dybvig, Printing floating point numbers
-        quickly and accurately, SIGPLAN notices 31, 5 (May 1996), 108-116.  */
-
-      width = fabs (data) < DBL_MIN ? 1 : DBL_DIG;
-      do
-       sprintf (buf, "%.*g", width, data);
-      while (width++ < DOUBLE_DIGITS_BOUND && atof (buf) != data);
+        floating point value without losing information.  */
+      dtoastr (buf, FLOAT_TO_STRING_BUFSIZE - 2, 0, 0, data);
+      /* The decimal point must be printed, or the byte compiler can
+        get confused (Bug#8033). */
+      width = 1;
     }
   else                 /* oink oink */
     {
       /* Check that the spec we have is fully valid.
         This means not only valid for printf,
         but meant for floats, and reasonable.  */
-      cp = SDATA (Vfloat_output_format);
+      cp = SSDATA (Vfloat_output_format);
 
       if (cp[0] != '%')
        goto lose;
@@ -1178,7 +1049,7 @@ float_to_string (unsigned char *buf, double data)
       if (cp[1] != 0)
        goto lose;
 
-      sprintf (buf, SDATA (Vfloat_output_format), data);
+      sprintf (buf, SSDATA (Vfloat_output_format), data);
     }
 
   /* Make sure there is a decimal point with digit after, or an
@@ -1196,8 +1067,7 @@ float_to_string (unsigned char *buf, double data)
          cp[1] = '0';
          cp[2] = 0;
        }
-
-      if (*cp == 0)
+      else if (*cp == 0)
        {
          *cp++ = '.';
          *cp++ = '0';
@@ -1226,33 +1096,24 @@ print (Lisp_Object obj, register Lisp_Object printcharfun, int escapeflag)
   /* Construct Vprint_number_table for print-gensym and print-circle.  */
   if (!NILP (Vprint_gensym) || !NILP (Vprint_circle))
     {
-      int i, start, 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);
 
-      /* Remove unnecessary objects, which appear only once in OBJ;
-        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);
-           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;
+      if (HASH_TABLE_P (Vprint_number_table))
+       { /* Remove unnecessary objects, which appear only once in OBJ;
+            that is, whose status is Qt.
+            Maybe a better way to do that is to copy elements to
+            a new hash table.  */
+         struct Lisp_Hash_Table *h = XHASH_TABLE (Vprint_number_table);
+         int i;
 
-      print_number_index = index;
+         for (i = 0; i < HASH_TABLE_SIZE (h); ++i)
+           if (!NILP (HASH_HASH (h, i))
+               && EQ (HASH_VALUE (h, i), Qt))
+             Fremhash (HASH_KEY (h, i), Vprint_number_table);
+       }
     }
 
   print_depth = 0;
@@ -1294,54 +1155,46 @@ print_preprocess (Lisp_Object obj)
 
  loop:
   if (STRINGP (obj) || CONSP (obj) || VECTORP (obj)
-      || FUNVECP (obj) || CHAR_TABLE_P (obj) || SUB_CHAR_TABLE_P (obj)
+      || COMPILEDP (obj) || CHAR_TABLE_P (obj) || SUB_CHAR_TABLE_P (obj)
       || HASH_TABLE_P (obj)
       || (! NILP (Vprint_gensym)
          && SYMBOLP (obj)
          && !SYMBOL_INTERNED_P (obj)))
     {
+      if (!HASH_TABLE_P (Vprint_number_table))
+       {
+         Lisp_Object args[2];
+         args[0] = QCtest;
+         args[1] = Qeq;
+         Vprint_number_table = Fmake_hash_table (2, args);
+       }
+
       /* In case print-circle is nil and print-gensym is t,
         add OBJ to Vprint_number_table only when OBJ is a symbol.  */
       if (! NILP (Vprint_circle) || SYMBOLP (obj))
        {
-         for (i = 0; i < print_number_index; i++)
-           if (EQ (PRINT_NUMBER_OBJECT (Vprint_number_table, i), obj))
-             {
-               /* OBJ appears more than once.  Let's remember that.  */
-               PRINT_NUMBER_STATUS (Vprint_number_table, i) = Qt;
-                print_depth--;
-               return;
-             }
-
-         /* OBJ is not yet recorded.  Let's add to the table.  */
-         if (print_number_index == 0)
-           {
-             /* Initialize the table.  */
-             Vprint_number_table = Fmake_vector (make_number (40), Qnil);
-           }
-         else if (XVECTOR (Vprint_number_table)->size == print_number_index * 2)
-           {
-             /* Reallocate the table.  */
-             int i = print_number_index * 4;
-             Lisp_Object old_table = Vprint_number_table;
-             Vprint_number_table = Fmake_vector (make_number (i), Qnil);
-             for (i = 0; i < print_number_index; i++)
+         Lisp_Object num = Fgethash (obj, Vprint_number_table, Qnil);
+         if (!NILP (num)
+             /* If Vprint_continuous_numbering is non-nil and OBJ is a gensym,
+                always print the gensym with a number.  This is a special for
+                the lisp function byte-compile-output-docform.  */
+             || (!NILP (Vprint_continuous_numbering)
+                 && SYMBOLP (obj)
+                 && !SYMBOL_INTERNED_P (obj)))
+           { /* OBJ appears more than once.    Let's remember that.  */
+             if (!INTEGERP (num))
                {
-                 PRINT_NUMBER_OBJECT (Vprint_number_table, i)
-                   = PRINT_NUMBER_OBJECT (old_table, i);
-                 PRINT_NUMBER_STATUS (Vprint_number_table, i)
-                   = PRINT_NUMBER_STATUS (old_table, i);
+                 print_number_index++;
+                 /* Negative number indicates it hasn't been printed yet.  */
+                 Fputhash (obj, make_number (- print_number_index),
+                           Vprint_number_table);
                }
+             print_depth--;
+             return;
            }
-         PRINT_NUMBER_OBJECT (Vprint_number_table, print_number_index) = obj;
-         /* If Vprint_continuous_numbering is non-nil and OBJ is a gensym,
-            always print the gensym with a number.  This is a special for
-            the lisp function byte-compile-output-docform.  */
-         if (!NILP (Vprint_continuous_numbering)
-             && SYMBOLP (obj)
-             && !SYMBOL_INTERNED_P (obj))
-           PRINT_NUMBER_STATUS (Vprint_number_table, print_number_index) = Qt;
-         print_number_index++;
+         else
+           /* OBJ is not yet recorded.  Let's add to the table.  */
+           Fputhash (obj, Qt, Vprint_number_table);
        }
 
       switch (XTYPE (obj))
@@ -1372,8 +1225,8 @@ print_preprocess (Lisp_Object obj)
            print_preprocess (XVECTOR (obj)->contents[i]);
          if (HASH_TABLE_P (obj))
            { /* For hash tables, the key_and_value slot is past
-               `size' because it needs to be marked specially in case
-               the table is weak.  */
+                `size' because it needs to be marked specially in case
+                the table is weak.  */
              struct Lisp_Hash_Table *h = XHASH_TABLE (obj);
              print_preprocess (h->key_and_value);
            }
@@ -1392,16 +1245,12 @@ print_preprocess_string (INTERVAL interval, Lisp_Object arg)
   print_preprocess (interval->plist);
 }
 
-/* A flag to control printing of `charset' text property.
-   The default value is Qdefault. */
-Lisp_Object Vprint_charset_text_property;
-
 static void print_check_string_charset_prop (INTERVAL interval, Lisp_Object string);
 
 #define PRINT_STRING_NON_CHARSET_FOUND 1
 #define PRINT_STRING_UNSAFE_CHARSET_FOUND 2
 
-/* Bitwize or of the abobe macros. */
+/* Bitwise or of the above macros. */
 static int print_check_string_result;
 
 static void
@@ -1430,8 +1279,8 @@ print_check_string_charset_prop (INTERVAL interval, Lisp_Object string)
       || ! (print_check_string_result & PRINT_STRING_UNSAFE_CHARSET_FOUND))
     {
       int i, c;
-      int charpos = interval->position;
-      int bytepos = string_char_to_byte (string, charpos);
+      EMACS_INT charpos = interval->position;
+      EMACS_INT bytepos = string_char_to_byte (string, charpos);
       Lisp_Object charset;
 
       charset = XCAR (XCDR (val));
@@ -1488,7 +1337,7 @@ print_object (Lisp_Object obj, register Lisp_Object printcharfun, int escapeflag
 
   /* Detect circularities and truncate them.  */
   if (STRINGP (obj) || CONSP (obj) || VECTORP (obj)
-      || FUNVECP (obj) || CHAR_TABLE_P (obj) || SUB_CHAR_TABLE_P (obj)
+      || COMPILEDP (obj) || CHAR_TABLE_P (obj) || SUB_CHAR_TABLE_P (obj)
       || HASH_TABLE_P (obj)
       || (! NILP (Vprint_gensym)
          && SYMBOLP (obj)
@@ -1510,28 +1359,26 @@ print_object (Lisp_Object obj, register Lisp_Object printcharfun, int escapeflag
       else
        {
          /* With the print-circle feature.  */
-         int i;
-         for (i = 0; i < print_number_index; i++)
-           if (EQ (PRINT_NUMBER_OBJECT (Vprint_number_table, i), obj))
-             {
-               if (NILP (PRINT_NUMBER_STATUS (Vprint_number_table, i)))
-                 {
-                   /* Add a prefix #n= if OBJ has not yet been printed;
-                      that is, its status field is nil.  */
-                   sprintf (buf, "#%d=", i + 1);
-                   strout (buf, -1, -1, printcharfun, 0);
-                   /* OBJ is going to be printed.  Set the status to t.  */
-                   PRINT_NUMBER_STATUS (Vprint_number_table, i) = Qt;
-                   break;
-                 }
-               else
-                 {
-                   /* Just print #n# if OBJ has already been printed.  */
-                   sprintf (buf, "#%d#", i + 1);
-                   strout (buf, -1, -1, printcharfun, 0);
-                   return;
-                 }
-             }
+         Lisp_Object num = Fgethash (obj, Vprint_number_table, Qnil);
+         if (INTEGERP (num))
+           {
+             int n = XINT (num);
+             if (n < 0)
+               { /* Add a prefix #n= if OBJ has not yet been printed;
+                    that is, its status field is nil.  */
+                 sprintf (buf, "#%d=", -n);
+                 strout (buf, -1, -1, printcharfun, 0);
+                 /* OBJ is going to be printed.  Remember that fact.  */
+                 Fputhash (obj, make_number (- n), Vprint_number_table);
+               }
+             else
+               {
+                 /* Just print #n# if OBJ has already been printed.  */
+                 sprintf (buf, "#%d#", n);
+                 strout (buf, -1, -1, printcharfun, 0);
+                 return;
+               }
+           }
        }
     }
 
@@ -1551,7 +1398,7 @@ print_object (Lisp_Object obj, register Lisp_Object printcharfun, int escapeflag
 
     case Lisp_Float:
       {
-       char pigbuf[350];       /* see comments in float_to_string */
+       char pigbuf[FLOAT_TO_STRING_BUFSIZE];
 
        float_to_string (pigbuf, XFLOAT_DATA (obj));
        strout (pigbuf, -1, -1, printcharfun, 0);
@@ -1563,10 +1410,10 @@ print_object (Lisp_Object obj, register Lisp_Object printcharfun, int escapeflag
        print_string (obj, printcharfun);
       else
        {
-         register int i, i_byte;
+         register EMACS_INT i, i_byte;
          struct gcpro gcpro1;
          unsigned char *str;
-         int size_byte;
+         EMACS_INT size_byte;
          /* 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;
@@ -1615,7 +1462,7 @@ print_object (Lisp_Object obj, register Lisp_Object printcharfun, int escapeflag
                  PRINTCHAR ('f');
                }
              else if (multibyte
-                      && (CHAR_BYTE8_P (c) 
+                      && (CHAR_BYTE8_P (c)
                           || (! ASCII_CHAR_P (c) && print_escape_multibyte)))
                {
                  /* When multibyte is disabled,
@@ -1623,7 +1470,7 @@ print_object (Lisp_Object obj, register Lisp_Object printcharfun, int escapeflag
                     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];
+                 char outbuf[50];
 
                  if (CHAR_BYTE8_P (c))
                    sprintf (outbuf, "\\%03o", CHAR_TO_BYTE8 (c));
@@ -1642,7 +1489,7 @@ print_object (Lisp_Object obj, register Lisp_Object printcharfun, int escapeflag
                     or when explicitly requested,
                     print single-byte non-ASCII string chars
                     using octal escapes.  */
-                 unsigned char outbuf[5];
+                 char outbuf[5];
                  sprintf (outbuf, "\\%03o", c);
                  strout (outbuf, -1, -1, printcharfun, 0);
                }
@@ -1684,7 +1531,8 @@ print_object (Lisp_Object obj, register Lisp_Object printcharfun, int escapeflag
        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;
+       int i, i_byte;
+       EMACS_INT size_byte;
        Lisp_Object name;
 
        name = SYMBOL_NAME (obj);
@@ -1782,28 +1630,9 @@ print_object (Lisp_Object obj, register Lisp_Object printcharfun, int escapeflag
        {
          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 (' ');
-
-             print_object (XCAR (XCDR (tem)), printcharfun, 0);
-             PRINTCHAR (')');
-
-             obj = XCDR (obj);
-           }
-
          {
-           int print_length, i;
+           EMACS_INT print_length;
+           int i;
            Lisp_Object halftail = obj;
 
            /* Negative values of print-length are invalid in CL.
@@ -1832,23 +1661,13 @@ print_object (Lisp_Object obj, register Lisp_Object printcharfun, int escapeflag
                    /* With the print-circle feature.  */
                    if (i != 0)
                      {
-                       int i;
-                       for (i = 0; i < print_number_index; i++)
-                         if (EQ (PRINT_NUMBER_OBJECT (Vprint_number_table, i),
-                                 obj))
-                           {
-                             if (NILP (PRINT_NUMBER_STATUS (Vprint_number_table, i)))
-                               {
-                                 strout (" . ", 3, 3, printcharfun, 0);
-                                 print_object (obj, printcharfun, escapeflag);
-                               }
-                             else
-                               {
-                                 sprintf (buf, " . #%d#", i + 1);
-                                 strout (buf, -1, -1, printcharfun, 0);
-                               }
-                             goto end_of_list;
-                           }
+                       Lisp_Object num = Fgethash (obj, Vprint_number_table, Qnil);
+                       if (INTEGERP (num))
+                         {
+                           strout (" . ", 3, 3, printcharfun, 0);
+                           print_object (obj, printcharfun, escapeflag);
+                           goto end_of_list;
+                         }
                      }
                  }
 
@@ -1898,7 +1717,7 @@ print_object (Lisp_Object obj, register Lisp_Object printcharfun, int escapeflag
          register int i;
          register unsigned char c;
          struct gcpro gcpro1;
-         int size_in_chars
+         EMACS_INT size_in_chars
            = ((XBOOL_VECTOR (obj)->size + BOOL_VECTOR_BITS_PER_CHAR - 1)
               / BOOL_VECTOR_BITS_PER_CHAR);
 
@@ -1964,7 +1783,7 @@ print_object (Lisp_Object obj, register Lisp_Object printcharfun, int escapeflag
          if (!NILP (XWINDOW (obj)->buffer))
            {
              strout (" on ", -1, -1, printcharfun, 0);
-             print_string (XBUFFER (XWINDOW (obj)->buffer)->name, printcharfun);
+             print_string (BVAR (XBUFFER (XWINDOW (obj)->buffer), name), printcharfun);
            }
          PRINTCHAR ('>');
        }
@@ -1984,7 +1803,8 @@ print_object (Lisp_Object obj, register Lisp_Object printcharfun, int escapeflag
       else if (HASH_TABLE_P (obj))
        {
          struct Lisp_Hash_Table *h = XHASH_TABLE (obj);
-         int i, real_size, size;
+         int i;
+         EMACS_INT real_size, size;
 #if 0
          strout ("#<hash-table", -1, -1, printcharfun, 0);
          if (SYMBOLP (h->test))
@@ -2013,25 +1833,25 @@ print_object (Lisp_Object obj, register Lisp_Object printcharfun, int escapeflag
          if (!NILP (h->test))
            {
              strout (" test ", -1, -1, printcharfun, 0);
-             print_object (h->test, printcharfun, 0);
+             print_object (h->test, printcharfun, escapeflag);
            }
 
          if (!NILP (h->weak))
            {
              strout (" weakness ", -1, -1, printcharfun, 0);
-             print_object (h->weak, printcharfun, 0);
+             print_object (h->weak, printcharfun, escapeflag);
            }
 
          if (!NILP (h->rehash_size))
            {
              strout (" rehash-size ", -1, -1, printcharfun, 0);
-             print_object (h->rehash_size, printcharfun, 0);
+             print_object (h->rehash_size, printcharfun, escapeflag);
            }
 
          if (!NILP (h->rehash_threshold))
            {
              strout (" rehash-threshold ", -1, -1, printcharfun, 0);
-             print_object (h->rehash_threshold, printcharfun, 0);
+             print_object (h->rehash_threshold, printcharfun, escapeflag);
            }
 
          strout (" data ", -1, -1, printcharfun, 0);
@@ -2044,15 +1864,15 @@ print_object (Lisp_Object obj, register Lisp_Object printcharfun, int escapeflag
          if (NATNUMP (Vprint_length)
              && XFASTINT (Vprint_length) < size)
            size = XFASTINT (Vprint_length);
-         
+
          PRINTCHAR ('(');
          for (i = 0; i < size; i++)
            if (!NILP (HASH_HASH (h, i)))
              {
                if (i) PRINTCHAR (' ');
-               print_object (HASH_KEY (h, i), printcharfun, 1);
+               print_object (HASH_KEY (h, i), printcharfun, escapeflag);
                PRINTCHAR (' ');
-               print_object (HASH_VALUE (h, i), printcharfun, 1);
+               print_object (HASH_VALUE (h, i), printcharfun, escapeflag);
              }
 
          if (size < real_size)
@@ -2064,16 +1884,16 @@ print_object (Lisp_Object obj, register Lisp_Object printcharfun, int escapeflag
        }
       else if (BUFFERP (obj))
        {
-         if (NILP (XBUFFER (obj)->name))
+         if (NILP (BVAR (XBUFFER (obj), name)))
            strout ("#<killed buffer>", -1, -1, printcharfun, 0);
          else if (escapeflag)
            {
              strout ("#<buffer ", -1, -1, printcharfun, 0);
-             print_string (XBUFFER (obj)->name, printcharfun);
+             print_string (BVAR (XBUFFER (obj), name), printcharfun);
              PRINTCHAR ('>');
            }
          else
-           print_string (XBUFFER (obj)->name, printcharfun);
+           print_string (BVAR (XBUFFER (obj), name), printcharfun);
        }
       else if (WINDOW_CONFIGURATIONP (obj))
        {
@@ -2120,7 +1940,7 @@ print_object (Lisp_Object obj, register Lisp_Object printcharfun, int escapeflag
       else
        {
          EMACS_INT size = XVECTOR (obj)->size;
-         if (FUNVECP (obj))
+         if (COMPILEDP (obj))
            {
              PRINTCHAR ('#');
              size &= PSEUDOVECTOR_SIZE_MASK;
@@ -2150,7 +1970,7 @@ print_object (Lisp_Object obj, register Lisp_Object printcharfun, int escapeflag
          {
            register int i;
            register Lisp_Object tem;
-           int real_size = size;
+           EMACS_INT real_size = size;
 
            /* Don't print more elements than the specified maximum.  */
            if (NATNUMP (Vprint_length)
@@ -2182,10 +2002,10 @@ print_object (Lisp_Object obj, register Lisp_Object printcharfun, int escapeflag
            strout ("in no buffer", -1, -1, printcharfun, 0);
          else
            {
-             sprintf (buf, "at %d", marker_position (obj));
+             sprintf (buf, "at %ld", (long)marker_position (obj));
              strout (buf, -1, -1, printcharfun, 0);
              strout (" in ", -1, -1, printcharfun, 0);
-             print_string (XMARKER (obj)->buffer->name, printcharfun);
+             print_string (BVAR (XMARKER (obj)->buffer, name), printcharfun);
            }
          PRINTCHAR ('>');
          break;
@@ -2196,11 +2016,11 @@ print_object (Lisp_Object obj, register Lisp_Object printcharfun, int escapeflag
            strout ("in no buffer", -1, -1, printcharfun, 0);
          else
            {
-             sprintf (buf, "from %d to %d in ",
-                      marker_position (OVERLAY_START (obj)),
-                      marker_position (OVERLAY_END   (obj)));
+             sprintf (buf, "from %ld to %ld in ",
+                      (long)marker_position (OVERLAY_START (obj)),
+                      (long)marker_position (OVERLAY_END   (obj)));
              strout (buf, -1, -1, printcharfun, 0);
-             print_string (XMARKER (OVERLAY_START (obj))->buffer->name,
+             print_string (BVAR (XMARKER (OVERLAY_START (obj))->buffer, name),
                            printcharfun);
            }
          PRINTCHAR ('>');
@@ -2272,7 +2092,7 @@ syms_of_print (void)
   Qtemp_buffer_setup_hook = intern_c_string ("temp-buffer-setup-hook");
   staticpro (&Qtemp_buffer_setup_hook);
 
-  DEFVAR_LISP ("standard-output", &Vstandard_output,
+  DEFVAR_LISP ("standard-output", Vstandard_output,
               doc: /* Output stream `print' uses by default for outputting a character.
 This may be any function of one argument.
 It may also be a buffer (output is inserted before point)
@@ -2282,7 +2102,7 @@ or the symbol t (output appears in the echo area).  */);
   Qstandard_output = intern_c_string ("standard-output");
   staticpro (&Qstandard_output);
 
-  DEFVAR_LISP ("float-output-format", &Vfloat_output_format,
+  DEFVAR_LISP ("float-output-format", Vfloat_output_format,
               doc: /* The format descriptor string used to print floats.
 This is a %-spec like those accepted by `printf' in C,
 but with some restrictions.  It must start with the two characters `%.'.
@@ -2302,22 +2122,22 @@ that represents the number without losing information.  */);
   Qfloat_output_format = intern_c_string ("float-output-format");
   staticpro (&Qfloat_output_format);
 
-  DEFVAR_LISP ("print-length", &Vprint_length,
+  DEFVAR_LISP ("print-length", Vprint_length,
               doc: /* Maximum length of list to print before abbreviating.
 A value of nil means no limit.  See also `eval-expression-print-length'.  */);
   Vprint_length = Qnil;
 
-  DEFVAR_LISP ("print-level", &Vprint_level,
+  DEFVAR_LISP ("print-level", Vprint_level,
               doc: /* Maximum depth of list nesting to print before abbreviating.
 A value of nil means no limit.  See also `eval-expression-print-level'.  */);
   Vprint_level = Qnil;
 
-  DEFVAR_BOOL ("print-escape-newlines", &print_escape_newlines,
+  DEFVAR_BOOL ("print-escape-newlines", print_escape_newlines,
               doc: /* Non-nil means print newlines in strings as `\\n'.
 Also print formfeeds as `\\f'.  */);
   print_escape_newlines = 0;
 
-  DEFVAR_BOOL ("print-escape-nonascii", &print_escape_nonascii,
+  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'.
@@ -2325,18 +2145,18 @@ 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,
+  DEFVAR_BOOL ("print-escape-multibyte", print_escape_multibyte,
               doc: /* Non-nil means print multibyte characters in strings as \\xXXXX.
 \(XXXX is the hex representation of the character code.)
 This affects only `prin1'.  */);
   print_escape_multibyte = 0;
 
-  DEFVAR_BOOL ("print-quoted", &print_quoted,
+  DEFVAR_BOOL ("print-quoted", print_quoted,
               doc: /* Non-nil means print quoted forms with reader syntax.
 I.e., (quote foo) prints as 'foo, (function foo) as #'foo.  */);
   print_quoted = 0;
 
-  DEFVAR_LISP ("print-gensym", &Vprint_gensym,
+  DEFVAR_LISP ("print-gensym", Vprint_gensym,
               doc: /* Non-nil means print uninterned symbols so they will read as uninterned.
 I.e., the value of (make-symbol \"foobar\") prints as #:foobar.
 When the uninterned symbol appears within a recursive data structure,
@@ -2345,7 +2165,7 @@ constructs as needed, so that multiple references to the same symbol are
 shared once again when the text is read back.  */);
   Vprint_gensym = Qnil;
 
-  DEFVAR_LISP ("print-circle", &Vprint_circle,
+  DEFVAR_LISP ("print-circle", Vprint_circle,
               doc: /* *Non-nil means print recursive structures using #N= and #N# syntax.
 If nil, printing proceeds recursively and may lead to
 `max-lisp-eval-depth' being exceeded or an error may occur:
@@ -2357,14 +2177,14 @@ representation) and `#N#' in place of each subsequent occurrence,
 where N is a positive decimal integer.  */);
   Vprint_circle = Qnil;
 
-  DEFVAR_LISP ("print-continuous-numbering", &Vprint_continuous_numbering,
+  DEFVAR_LISP ("print-continuous-numbering", Vprint_continuous_numbering,
               doc: /* *Non-nil means number continuously across print calls.
 This affects the numbers printed for #N= labels and #M# references.
 See also `print-circle', `print-gensym', and `print-number-table'.
 This variable should not be set with `setq'; bind it with a `let' instead.  */);
   Vprint_continuous_numbering = Qnil;
 
-  DEFVAR_LISP ("print-number-table", &Vprint_number_table,
+  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.
@@ -2377,7 +2197,7 @@ 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;
 
-  DEFVAR_LISP ("print-charset-text-property", &Vprint_charset_text_property,
+  DEFVAR_LISP ("print-charset-text-property", Vprint_charset_text_property,
               doc: /* A flag to control printing of `charset' text property on printing a string.
 The value must be nil, t, or `default'.
 
@@ -2419,9 +2239,4 @@ priorities.  */);
 
   print_prune_charset_plist = Qnil;
   staticpro (&print_prune_charset_plist);
-
-  defsubr (&Swith_output_to_temp_buffer);
 }
-
-/* arch-tag: bc797170-94ae-41de-86e3-75e20f8f7a39
-   (do not change this comment) */