+ int i;
+ struct Lisp_Save_Value *v = XSAVE_VALUE (obj);
+
+ strout ("#<save-value ", -1, -1, printcharfun);
+
+ if (v->area)
+ {
+ ptrdiff_t amount = v->data[1].integer;
+
+#if GC_MARK_STACK
+
+ /* If GC_MARK_STACK, valid_lisp_object_p is quite reliable,
+ and so we try to print up to 8 objects we have saved.
+ Although valid_lisp_object_p is slow, this shouldn't be
+ a real bottleneck because we do not use this code under
+ normal circumstances. */
+
+ 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 */
+
+ /* If !GC_MARK_STACK, we have no reliable way to find
+ whether Lisp_Object pointers points to an initialized
+ objects, and so we do not ever trying to print them. */
+
+ i = sprintf (buf, "with %"pD"d objects", amount);
+ strout (buf, i, i, printcharfun);
+
+#endif /* GC_MARK_STACK */
+ }
+ else
+ {
+ /* Print each `data[N]' slot according to its type. */
+
+#define PRINTX(index) \
+ do { \
+ i = 0; \
+ if (v->type ## index == SAVE_UNUSED) \
+ i = sprintf (buf, "<unused>"); \
+ else if (v->type ## index == SAVE_INTEGER) \
+ i = sprintf (buf, "<integer %"pD"d>", v->data[index].integer); \
+ else if (v->type ## index == SAVE_POINTER) \
+ i = sprintf (buf, "<pointer %p>", v->data[index].pointer); \
+ else /* SAVE_OBJECT */ \
+ print_object (v->data[index].object, printcharfun, escapeflag); \
+ if (i) \
+ strout (buf, i, i, printcharfun); \
+ } while (0)
+
+ PRINTX (0);
+ PRINTCHAR (' ');
+ PRINTX (1);
+ PRINTCHAR (' ');
+ PRINTX (2);
+ PRINTCHAR (' ');
+ PRINTX (3);
+
+#undef PRINTX
+
+ }
+ PRINTCHAR ('>');