+ int i;
+ struct Lisp_Save_Value *v = XSAVE_VALUE (obj);
+
+ strout ("#<save-value ", -1, -1, printcharfun);
+
+ if (v->save_type == SAVE_TYPE_MEMORY)
+ {
+ ptrdiff_t amount = v->data[1].integer;
+
+#if GC_MARK_STACK
+
+ /* valid_lisp_object_p is reliable, so try to print up
+ to 8 saved objects. This code is rarely used, so
+ it's OK that valid_lisp_object_p is slow. */
+
+ int limit = min (amount, 8);
+ Lisp_Object *area = v->data[0].pointer;
+
+ i = sprintf (buf, "with %"pD"d objects", amount);
+ strout (buf, i, i, printcharfun);
+
+ for (i = 0; i < limit; i++)
+ {
+ Lisp_Object maybe = area[i];
+
+ if (valid_lisp_object_p (maybe) > 0)
+ {
+ PRINTCHAR (' ');
+ print_object (maybe, printcharfun, escapeflag);
+ }
+ else
+ strout (" <invalid>", -1, -1, printcharfun);
+ }
+ if (i == limit && i < amount)
+ strout (" ...", 4, 4, printcharfun);
+
+#else /* not GC_MARK_STACK */
+
+ /* There is no reliable way to determine whether the objects
+ are initialized, so do not try to print them. */
+
+ i = sprintf (buf, "with %"pD"d objects", amount);
+ strout (buf, i, i, printcharfun);
+
+#endif /* GC_MARK_STACK */
+ }
+ else
+ {
+ /* Print each slot according to its type. */
+ int index;
+ for (index = 0; index < SAVE_VALUE_SLOTS; index++)
+ {
+ if (index)
+ PRINTCHAR (' ');
+
+ switch (save_type (v, index))
+ {
+ case SAVE_UNUSED:
+ i = sprintf (buf, "<unused>");
+ break;
+
+ case SAVE_POINTER:
+ i = sprintf (buf, "<pointer %p>",
+ v->data[index].pointer);
+ break;
+
+ case SAVE_FUNCPOINTER:
+ i = sprintf (buf, "<funcpointer %p>",
+ ((void *) (intptr_t)
+ v->data[index].funcpointer));
+ break;
+
+ case SAVE_INTEGER:
+ i = sprintf (buf, "<integer %"pD"d>",
+ v->data[index].integer);
+ break;
+
+ case SAVE_OBJECT:
+ print_object (v->data[index].object, printcharfun,
+ escapeflag);
+ continue;
+
+ default:
+ emacs_abort ();
+ }
+
+ strout (buf, i, i, printcharfun);
+ }
+ }
+ PRINTCHAR ('>');