Fix #+(and immobile-space (not compact-instance-header)) some more
[sbcl.git] / src / runtime / print.c
blob263397f0c55d36332a43ab04ce8e622a263d82c5
1 /* code for low-level debugging/diagnostic output */
3 /*
4 * This software is part of the SBCL system. See the README file for
5 * more information.
7 * This software is derived from the CMU CL system, which was
8 * written at Carnegie Mellon University and released into the
9 * public domain. The software is in the public domain and is
10 * provided with absolutely no warranty. See the COPYING and CREDITS
11 * files for more information.
15 * FIXME:
16 * Some of the code in here is deeply broken, depending on guessing
17 * already out-of-date values instead of getting them from sbcl.h.
20 #include <stdio.h>
21 #include <string.h>
23 #include "sbcl.h"
24 #include "print.h"
25 #include "runtime.h"
26 #include "gc-internal.h"
27 #include <stdarg.h>
28 #include "thread.h" /* genesis/primitive-objects.h needs this */
29 #include <errno.h>
30 #include <stdlib.h>
32 /* FSHOW and odxprint provide debugging output for low-level information
33 * (signal handling, exceptions, safepoints) which is hard to debug by
34 * other means.
36 * If enabled at all, environment variables control whether calls of the
37 * form odxprint(name, ...) are enabled at run-time, e.g. using
38 * SBCL_DYNDEBUG="fshow fshow_signal safepoints".
40 * In the case of FSHOW and FSHOW_SIGNAL, old-style code from runtime.h
41 * can also be used to enable or disable these more aggressively.
44 struct dyndebug_config dyndebug_config = {
45 QSHOW == 2, QSHOW_SIGNALS == 2
48 void
49 dyndebug_init()
51 #define DYNDEBUG_NFLAGS (sizeof(struct dyndebug_config) / sizeof(int))
52 #define dyndebug_init1(lowercase, uppercase) \
53 do { \
54 int *ptr = &dyndebug_config.dyndebug_##lowercase; \
55 ptrs[n] = ptr; \
56 names[n] = #lowercase; \
57 char *val = getenv("SBCL_DYNDEBUG__" uppercase); \
58 *ptr = val && strlen(val); \
59 n++; \
60 } while (0)
61 int n = 0;
62 char *names[DYNDEBUG_NFLAGS];
63 int *ptrs[DYNDEBUG_NFLAGS];
65 dyndebug_init1(fshow, "FSHOW");
66 dyndebug_init1(fshow_signal, "FSHOW_SIGNAL");
67 dyndebug_init1(gencgc_verbose, "GENCGC_VERBOSE");
68 dyndebug_init1(safepoints, "SAFEPOINTS");
69 dyndebug_init1(seh, "SEH");
70 dyndebug_init1(misc, "MISC");
71 dyndebug_init1(pagefaults, "PAGEFAULTS");
72 dyndebug_init1(io, "IO");
73 dyndebug_init1(runtime_link, "RUNTIME_LINK");
75 int n_output_flags = n;
76 dyndebug_init1(backtrace_when_lost, "BACKTRACE_WHEN_LOST");
77 dyndebug_init1(sleep_when_lost, "SLEEP_WHEN_LOST");
79 if (n != DYNDEBUG_NFLAGS)
80 fprintf(stderr, "Bug in dyndebug_init\n");
82 #if defined(LISP_FEATURE_GENCGC)
83 gencgc_verbose = dyndebug_config.dyndebug_gencgc_verbose;
84 #endif
86 char *featurelist = getenv("SBCL_DYNDEBUG");
87 if (featurelist) {
88 int err = 0;
89 featurelist = strdup(featurelist);
90 char *ptr = featurelist;
91 for (;;) {
92 char *token = strtok(ptr, " ");
93 if (!token) break;
94 int i;
95 if (!strcmp(token, "all"))
96 for (i = 0; i < n_output_flags; i++)
97 *ptrs[i] = 1;
98 else {
99 for (i = 0; i < (int)DYNDEBUG_NFLAGS; i++)
100 if (!strcmp(token, names[i])) {
101 *ptrs[i] = 1;
102 break;
104 if (i == DYNDEBUG_NFLAGS) {
105 fprintf(stderr, "No such dyndebug flag: `%s'\n", token);
106 err = 1;
109 ptr = 0;
111 free(featurelist);
112 if (err) {
113 fprintf(stderr, "Valid flags are:\n");
114 fprintf(stderr, " all ;enables all of the following:\n");
115 int i;
116 for (i = 0; i < (int)DYNDEBUG_NFLAGS; i++) {
117 if (i == n_output_flags)
118 fprintf(stderr, "Additional options:\n");
119 fprintf(stderr, " %s\n", names[i]);
124 #undef dyndebug_init1
125 #undef DYNDEBUG_NFLAGS
128 /* Temporarily, odxprint merely performs the equivalent of a traditional
129 * FSHOW call, i.e. it merely formats to stderr. Ultimately, it should
130 * be restored to its full win32 branch functionality, where output to a
131 * file or to the debugger can be selected at runtime. */
133 void vodxprint_fun(const char *, va_list);
135 void
136 odxprint_fun(const char *fmt, ...)
138 va_list args;
139 va_start(args, fmt);
140 vodxprint_fun(fmt, args);
141 va_end(args);
144 void
145 vodxprint_fun(const char *fmt, va_list args)
147 #ifdef LISP_FEATURE_WIN32
148 DWORD lastError = GetLastError();
149 #endif
150 int original_errno = errno;
152 QSHOW_BLOCK;
154 char buf[1024];
155 int n = 0;
157 #ifdef LISP_FEATURE_SB_THREAD
158 struct thread *arch_os_get_current_thread(void);
159 struct thread *self = arch_os_get_current_thread();
160 void *pth = self ? (void *) self->os_thread : 0;
161 snprintf(buf, sizeof(buf), "[%p/%p] ", self, pth);
162 n = strlen(buf);
163 #endif
165 vsnprintf(buf + n, sizeof(buf) - n - 1, fmt, args);
166 /* buf is now zero-terminated (even in case of overflow).
167 * Our caller took care of the newline (if any) through `fmt'. */
169 /* A sufficiently POSIXy implementation of stdio will provide
170 * per-FILE locking, as defined in the spec for flockfile. At least
171 * glibc complies with this. Hence we do not need to perform
172 * locking ourselves here. (Should it turn out, of course, that
173 * other libraries opt for speed rather than safety, we need to
174 * revisit this decision.) */
175 fputs(buf, stderr);
177 #ifdef LISP_FEATURE_WIN32
178 /* stdio's stderr is line-bufferred, i.e. \n ought to flush it.
179 * Unfortunately, MinGW does not behave the way I would expect it
180 * to. Let's be safe: */
181 fflush(stderr);
182 #endif
184 QSHOW_UNBLOCK;
186 #ifdef LISP_FEATURE_WIN32
187 SetLastError(lastError);
188 #endif
189 errno = original_errno;
192 /* Translate the rather awkward syntax
193 * FSHOW((stderr, "xyz"))
194 * into the new and cleaner
195 * odxprint("xyz").
196 * If we were willing to clean up all existing call sites, we could remove
197 * this wrapper function. (This is a function, because I don't know how to
198 * strip the extra parens in a macro.) */
199 void
200 fshow_fun(void __attribute__((__unused__)) *ignored,
201 const char *fmt,
202 ...)
204 va_list args;
205 va_start(args, fmt);
206 vodxprint_fun(fmt, args);
207 va_end(args);
210 #include "monitor.h"
211 #include "vars.h"
212 #include "os.h"
213 #ifdef LISP_FEATURE_GENCGC
214 #include "gencgc-alloc-region.h" /* genesis/thread.h needs this */
215 #endif
216 #if defined(LISP_FEATURE_WIN32)
217 # include "win32-thread-private-events.h" /* genesis/thread.h needs this */
218 #endif
219 #include "genesis/static-symbols.h"
220 #include "genesis/primitive-objects.h"
221 #include "genesis/static-symbols.h"
222 #include "genesis/tagnames.h"
224 static int max_lines = 20, cur_lines = 0;
225 static int max_depth = 5, brief_depth = 2, cur_depth = 0;
226 static int max_length = 5;
227 static boolean dont_descend = 0, skip_newline = 0;
228 static int cur_clock = 0;
230 static void print_obj(char *prefix, lispobj obj);
232 #define NEWLINE_OR_RETURN if (continue_p(1)) newline(NULL); else return;
234 static void indent(int in)
236 static char *spaces = " ";
238 while (in > 64) {
239 fputs(spaces, stdout);
240 in -= 64;
242 if (in != 0)
243 fputs(spaces + 64 - in, stdout);
246 static boolean continue_p(boolean newline)
248 char buffer[256];
250 if (cur_depth >= max_depth || dont_descend)
251 return 0;
253 if (newline) {
254 if (skip_newline)
255 skip_newline = 0;
256 else
257 putchar('\n');
259 if (cur_lines >= max_lines) {
260 printf("More? [y] ");
261 fflush(stdout);
263 if (fgets(buffer, sizeof(buffer), stdin)) {
264 if (buffer[0] == 'n' || buffer[0] == 'N')
265 throw_to_monitor();
266 else
267 cur_lines = 0;
268 } else {
269 printf("\nUnable to read response, assuming y.\n");
270 cur_lines = 0;
275 return 1;
278 static void newline(char *label)
280 cur_lines++;
281 if (label != NULL)
282 fputs(label, stdout);
283 putchar('\t');
284 indent(cur_depth * 2);
288 static void print_unknown(lispobj obj)
290 printf("unknown object: %p", (void *)obj);
293 static void brief_fixnum(lispobj obj)
295 /* KLUDGE: Rather than update the tables in print_obj(), we
296 declare all fixnum-or-unknown tags to be fixnums and sort it
297 out here with a guard clause. */
298 if (!fixnump(obj)) return print_unknown(obj);
300 #ifndef LISP_FEATURE_ALPHA
301 printf("%ld", ((long)obj)>>N_FIXNUM_TAG_BITS);
302 #else
303 printf("%d", ((s32)obj)>>N_FIXNUM_TAG_BITS);
304 #endif
307 static void print_fixnum(lispobj obj)
309 /* KLUDGE: Rather than update the tables in print_obj(), we
310 declare all fixnum-or-unknown tags to be fixnums and sort it
311 out here with a guard clause. */
312 if (!fixnump(obj)) return print_unknown(obj);
314 #ifndef LISP_FEATURE_ALPHA
315 printf(": %ld", ((long)obj)>>N_FIXNUM_TAG_BITS);
316 #else
317 printf(": %d", ((s32)obj)>>N_FIXNUM_TAG_BITS);
318 #endif
321 static void brief_otherimm(lispobj obj)
323 int type, c;
324 char * charname = 0;
326 type = widetag_of(obj);
327 switch (type) {
328 case CHARACTER_WIDETAG:
329 c = obj>>8; // no mask. show whatever's there
330 printf("#\\");
331 switch (c) {
332 case '\0': charname = "Nul"; break;
333 case '\n': charname = "Newline"; break;
334 case '\b': charname = "Backspace"; break;
335 case '\177': charname = "Delete"; break;
336 default:
337 if (c < 32) printf("^%c", c+64);
338 else printf(c < 128 ? "%c" : "U+%X", c);
340 if (charname)
341 fputs(charname, stdout);
342 break;
344 case UNBOUND_MARKER_WIDETAG:
345 printf("<unbound marker>");
346 break;
348 default:
349 printf("%s", widetag_names[type >> 2]);
350 break;
354 static void print_otherimm(lispobj obj)
356 printf(", %s", widetag_names[widetag_of(obj) >> 2]);
358 switch (widetag_of(obj)) {
359 case CHARACTER_WIDETAG:
360 printf(": ");
361 brief_otherimm(obj);
362 break;
364 case SAP_WIDETAG:
365 case UNBOUND_MARKER_WIDETAG:
366 break;
368 default:
369 printf(": data=%"OBJ_FMTX, (obj>>8));
370 break;
374 static void brief_list(lispobj obj)
376 int space = 0;
377 int length = 0;
379 if (obj == NIL)
380 printf("NIL");
381 else {
382 putchar('(');
383 while (lowtag_of(obj) == LIST_POINTER_LOWTAG) {
384 if (space)
385 putchar(' ');
386 if (++length >= max_length) {
387 printf("...");
388 obj = NIL;
389 break;
391 print_obj("", CONS(obj)->car);
392 obj = CONS(obj)->cdr;
393 space = 1;
394 if (obj == NIL)
395 break;
397 if (obj != NIL) {
398 printf(" . ");
399 print_obj("", obj);
401 putchar(')');
405 static void print_list(lispobj obj)
407 if (obj == NIL) {
408 printf(" (NIL)");
409 } else {
410 print_obj("car: ", CONS(obj)->car);
411 print_obj("cdr: ", CONS(obj)->cdr);
415 // takes native pointer as input
416 char * simple_base_stringize(struct vector * string)
418 if (widetag_of(string->header) == SIMPLE_BASE_STRING_WIDETAG)
419 return (char*)string->data;
420 int length = string->length;
421 char * newstring = malloc(length+1);
422 uint32_t * data = (uint32_t*)string->data;
423 int i;
424 for(i=0;i<length;++i)
425 newstring[i] = data[i] < 128 ? data[i] : '?';
426 newstring[length] = 0;
427 return newstring;
430 static void brief_struct(lispobj obj)
432 struct instance *instance = (struct instance *)native_pointer(obj);
433 extern struct vector * instance_classoid_name(lispobj*);
434 struct vector * classoid_name;
435 classoid_name = instance_classoid_name((lispobj*)instance);
436 if ( classoid_name ) {
437 char * namestring = simple_base_stringize(classoid_name);
438 printf("#<ptr to %"OBJ_FMTX" %s instance>",
439 (uintptr_t)instance_layout((lispobj*)instance), namestring);
440 if ( namestring != (char*)classoid_name->data )
441 free(namestring);
442 } else {
443 printf("#<ptr to %"OBJ_FMTX" instance>",
444 (uintptr_t)instance_layout((lispobj*)instance));
448 #include "genesis/layout.h"
449 static boolean tagged_slot_p(struct layout *layout, int slot_index)
451 lispobj bitmap = layout->bitmap;
452 sword_t fixnum = (sword_t)bitmap >> N_FIXNUM_TAG_BITS; // optimistically
453 return fixnump(bitmap)
454 ? bitmap == make_fixnum(-1) ||
455 (slot_index < N_WORD_BITS && ((fixnum >> slot_index) & 1) != 0)
456 : positive_bignum_logbitp(slot_index,
457 (struct bignum*)native_pointer(bitmap));
460 static void print_struct(lispobj obj)
462 struct instance *instance = (struct instance *)native_pointer(obj);
463 unsigned int i;
464 char buffer[16];
465 lispobj layout = instance_layout(native_pointer(obj));
466 print_obj("type: ", layout);
467 for (i=INSTANCE_DATA_START; i<instance_length(instance->header); i++) {
468 sprintf(buffer, "slot %d: ", i);
469 if (layout && tagged_slot_p(LAYOUT(layout), i)) {
470 print_obj(buffer, instance->slots[i]);
471 } else {
472 newline(NULL);
473 printf("\n\t %s0x%"OBJ_FMTX" [raw]", buffer, instance->slots[i]);
478 void show_lstring(struct vector * string, int quotes, FILE *s)
480 int ucs4_p = 0;
481 int i, len = fixnum_value(string->length);
483 #ifdef SIMPLE_CHARACTER_STRING_WIDETAG
484 if (widetag_of(string->header) == SIMPLE_CHARACTER_STRING_WIDETAG) {
485 ucs4_p = 1;
486 if (quotes)
487 putc('u', s); /* an arbitrary notational convention */
489 #endif
490 if (quotes) putc('"', s);
491 for (i=0 ; i<len ; i++) {
492 // hopefully the compiler will optimize out the ucs4_p test
493 // when the runtime is built without Unicode support
494 int ch;
495 if (ucs4_p)
496 ch = i[(uint32_t*)string->data];
497 else
498 ch = i[(char*)string->data];
499 if (ch >= 32 && ch < 127) {
500 if (quotes && (ch == '"' || ch == '\\'))
501 putc('\\', s);
502 putc(ch, s);
503 } else {
504 fprintf(s, ch > 0xffff ? "\\U%08X" :
505 ch > 0xff ? "\\u%04X" : "\\x%02X", ch);
508 if (quotes) putc('"', s);
511 static void brief_otherptr(lispobj obj)
513 extern void safely_show_lstring(struct vector*, int, FILE*);
514 lispobj *ptr, header;
515 int type;
516 struct symbol *symbol;
518 ptr = native_pointer(obj);
519 header = *ptr;
520 type = widetag_of(header);
521 switch (type) {
522 case SYMBOL_WIDETAG:
523 symbol = (struct symbol *)ptr;
524 if (symbol->package == NIL)
525 printf("#:");
526 show_lstring(VECTOR(symbol->name), 0, stdout);
527 break;
529 case SIMPLE_BASE_STRING_WIDETAG:
530 #ifdef SIMPLE_CHARACTER_STRING_WIDETAG
531 case SIMPLE_CHARACTER_STRING_WIDETAG:
532 #endif
533 show_lstring((struct vector*)ptr, 1, stdout);
534 break;
536 default:
537 printf("#<ptr to ");
538 brief_otherimm(header);
539 if (type == FDEFN_WIDETAG) { // Try to print name, if a symbol
540 // FIXME: more address validity checks perhaps?
541 lispobj name = ((struct fdefn*)ptr)->name;
542 if (lowtag_of(name) == OTHER_POINTER_LOWTAG
543 && widetag_of(*native_pointer(name)) == SYMBOL_WIDETAG) {
544 printf(" for ");
545 struct vector* str = symbol_name(native_pointer(name));
546 safely_show_lstring(str, 0, stdout);
549 putchar('>');
553 static void print_slots(char **slots, int count, lispobj *ptr)
555 while (count-- > 0) {
556 if (*slots) {
557 print_obj(*slots++, *ptr++);
558 } else {
559 print_obj("???: ", *ptr++);
564 static lispobj symbol_function(lispobj* symbol)
566 lispobj info = ((struct symbol*)symbol)->info;
567 if (lowtag_of(info) == LIST_POINTER_LOWTAG)
568 info = CONS(info)->cdr;
569 if (lowtag_of(info) == OTHER_POINTER_LOWTAG) {
570 struct vector* v = VECTOR(info);
571 int len = fixnum_value(v->length);
572 if (len != 0) {
573 lispobj elt = v->data[0]; // Just like INFO-VECTOR-FDEFN
574 if (fixnump(elt) && (fixnum_value(elt) & 07777) >= 07701) {
575 lispobj fdefn = v->data[len-1];
576 if (lowtag_of(fdefn) == OTHER_POINTER_LOWTAG)
577 return FDEFN(fdefn)->fun;
581 return NIL;
584 static void print_otherptr(lispobj obj)
586 #ifndef LISP_FEATURE_ALPHA
587 lispobj *ptr;
588 unsigned long header;
589 unsigned long length;
590 #else
591 u32 *ptr;
592 u32 header;
593 u32 length;
594 #endif
595 int count, type, index;
596 char buffer[16];
598 ptr = native_pointer(obj);
599 if (ptr == NULL) {
600 printf(" (NULL Pointer)");
601 return;
604 header = *ptr++;
605 length = fixnum_value(*ptr);
606 count = HeaderValue(header);
607 type = widetag_of(header);
609 print_obj("header: ", header);
610 if (!other_immediate_lowtag_p(header)) {
611 NEWLINE_OR_RETURN;
612 printf("(invalid header object)");
613 return;
616 if (unprintable_array_types[type/8] & (1<<(type % 8)))
617 return;
618 switch (type) {
619 case BIGNUM_WIDETAG:
620 ptr += count;
621 NEWLINE_OR_RETURN;
622 printf("0x");
623 while (count-- > 0)
624 printf(
625 #if N_WORD_BITS == 32
626 "%08lx%s",
627 #else
628 "%016lx%s",
629 #endif
630 (unsigned long) *--ptr, (count?"_":""));
631 break;
633 case RATIO_WIDETAG:
634 print_slots(ratio_slots, count, ptr);
635 break;
637 case COMPLEX_WIDETAG:
638 print_slots(complex_slots, count, ptr);
639 break;
641 case SYMBOL_WIDETAG:
642 // Only 1 byte of a symbol header conveys its size.
643 // The other bytes may be freely used by the backend.
644 print_slots(symbol_slots, count & 0xFF, ptr);
645 if (symbol_function(ptr-1) != NIL)
646 print_obj("fun: ", symbol_function(ptr-1));
647 break;
649 #if N_WORD_BITS == 32
650 case SINGLE_FLOAT_WIDETAG:
651 NEWLINE_OR_RETURN;
652 printf("%g", ((struct single_float *)native_pointer(obj))->value);
653 break;
654 #endif
655 case DOUBLE_FLOAT_WIDETAG:
656 NEWLINE_OR_RETURN;
657 printf("%g", ((struct double_float *)native_pointer(obj))->value);
658 break;
660 #ifdef LONG_FLOAT_WIDETAG
661 case LONG_FLOAT_WIDETAG:
662 NEWLINE_OR_RETURN;
663 printf("%Lg", ((struct long_float *)native_pointer(obj))->value);
664 break;
665 #endif
667 #ifdef COMPLEX_SINGLE_FLOAT_WIDETAG
668 case COMPLEX_SINGLE_FLOAT_WIDETAG:
669 NEWLINE_OR_RETURN;
670 #ifdef LISP_FEATURE_64_BIT
671 printf("%g", ((struct complex_single_float *)native_pointer(obj))->data.data[0]);
672 #else
673 printf("%g", ((struct complex_single_float *)native_pointer(obj))->real);
674 #endif
675 NEWLINE_OR_RETURN;
676 #ifdef LISP_FEATURE_64_BIT
677 printf("%g", ((struct complex_single_float *)native_pointer(obj))->data.data[1]);
678 #else
679 printf("%g", ((struct complex_single_float *)native_pointer(obj))->imag);
680 #endif
681 break;
682 #endif
684 #ifdef COMPLEX_DOUBLE_FLOAT_WIDETAG
685 case COMPLEX_DOUBLE_FLOAT_WIDETAG:
686 NEWLINE_OR_RETURN;
687 printf("%g", ((struct complex_double_float *)native_pointer(obj))->real);
688 NEWLINE_OR_RETURN;
689 printf("%g", ((struct complex_double_float *)native_pointer(obj))->imag);
690 break;
691 #endif
693 #ifdef COMPLEX_LONG_FLOAT_WIDETAG
694 case COMPLEX_LONG_FLOAT_WIDETAG:
695 NEWLINE_OR_RETURN;
696 printf("%Lg", ((struct complex_long_float *)native_pointer(obj))->real);
697 NEWLINE_OR_RETURN;
698 printf("%Lg", ((struct complex_long_float *)native_pointer(obj))->imag);
699 break;
700 #endif
702 case SIMPLE_BASE_STRING_WIDETAG:
703 #ifdef SIMPLE_CHARACTER_STRING_WIDETAG
704 case SIMPLE_CHARACTER_STRING_WIDETAG:
705 #endif
706 NEWLINE_OR_RETURN;
707 show_lstring((struct vector*)native_pointer(obj), 1, stdout);
708 break;
710 case SIMPLE_VECTOR_WIDETAG:
711 NEWLINE_OR_RETURN;
712 printf("length = %ld", length);
713 ptr++;
714 index = 0;
715 while (length-- > 0) {
716 sprintf(buffer, "%d: ", index++);
717 print_obj(buffer, *ptr++);
719 break;
721 // FIXME: This case looks unreachable. print_struct() does it
722 case INSTANCE_WIDETAG:
723 NEWLINE_OR_RETURN;
724 count &= SHORT_HEADER_MAX_WORDS;
725 printf("length = %ld", (long) count);
726 index = 0;
727 while (count-- > 0) {
728 sprintf(buffer, "%d: ", index++);
729 print_obj(buffer, *ptr++);
731 break;
733 case CODE_HEADER_WIDETAG:
734 count &= SHORT_HEADER_MAX_WORDS;
735 // ptr was already bumped up
736 for_each_simple_fun(fun_index, fun, (struct code*)(ptr-1), 0, {
737 sprintf(buffer, "f[%d]: ", fun_index);
738 print_obj(buffer, make_lispobj(fun,FUN_POINTER_LOWTAG));
740 print_slots(code_slots, count-1, ptr);
741 break;
743 case SIMPLE_FUN_WIDETAG:
744 print_obj("code: ",
745 make_lispobj(native_pointer((lispobj)(ptr-1))
746 -(HeaderValue(header)&0xFFFF),
747 OTHER_POINTER_LOWTAG));
748 print_slots(simple_fun_slots,
749 sizeof simple_fun_slots/sizeof(char*)-1, ptr);
750 break;
752 #ifdef RETURN_PC_WIDETAG
753 case RETURN_PC_WIDETAG:
754 print_obj("code: ", obj - (count * 4));
755 break;
756 #endif
758 case CLOSURE_WIDETAG:
759 print_slots(closure_slots,
760 count & SHORT_HEADER_MAX_WORDS, ptr);
761 break;
763 case FUNCALLABLE_INSTANCE_WIDETAG:
764 print_slots(funcallable_instance_slots,
765 count & SHORT_HEADER_MAX_WORDS, ptr);
766 break;
768 case VALUE_CELL_WIDETAG:
769 print_slots(value_cell_slots, 1, ptr);
770 break;
772 case SAP_WIDETAG:
773 NEWLINE_OR_RETURN;
774 #ifndef LISP_FEATURE_ALPHA
775 printf("0x%08lx", (unsigned long) *ptr);
776 #else
777 printf("0x%016lx", *(lispobj*)(ptr+1));
778 #endif
779 break;
781 case WEAK_POINTER_WIDETAG:
782 print_slots(weak_pointer_slots, 1, ptr);
783 break;
785 case CHARACTER_WIDETAG:
786 case UNBOUND_MARKER_WIDETAG:
787 NEWLINE_OR_RETURN;
788 printf("pointer to an immediate?");
789 break;
791 case FDEFN_WIDETAG:
792 print_slots(fdefn_slots, 2, ptr);
793 print_obj("entry: ", fdefn_callee_lispobj((struct fdefn*)(ptr-1)));
794 break;
796 default:
797 NEWLINE_OR_RETURN;
798 printf("Unknown header object?");
799 break;
803 static void print_obj(char *prefix, lispobj obj)
805 #ifdef LISP_FEATURE_64_BIT
806 static void (*verbose_fns[])(lispobj obj)
807 = {print_fixnum, print_otherimm, print_fixnum, print_struct,
808 print_fixnum, print_otherimm, print_fixnum, print_list,
809 print_fixnum, print_otherimm, print_fixnum, print_otherptr,
810 print_fixnum, print_otherimm, print_fixnum, print_otherptr};
811 static void (*brief_fns[])(lispobj obj)
812 = {brief_fixnum, brief_otherimm, brief_fixnum, brief_struct,
813 brief_fixnum, brief_otherimm, brief_fixnum, brief_list,
814 brief_fixnum, brief_otherimm, brief_fixnum, brief_otherptr,
815 brief_fixnum, brief_otherimm, brief_fixnum, brief_otherptr};
816 #else
817 static void (*verbose_fns[])(lispobj obj)
818 = {print_fixnum, print_struct, print_otherimm, print_list,
819 print_fixnum, print_otherptr, print_otherimm, print_otherptr};
820 static void (*brief_fns[])(lispobj obj)
821 = {brief_fixnum, brief_struct, brief_otherimm, brief_list,
822 brief_fixnum, brief_otherptr, brief_otherimm, brief_otherptr};
823 #endif
824 int type = lowtag_of(obj);
825 struct var *var = lookup_by_obj(obj);
826 char buffer[256];
827 boolean verbose = cur_depth < brief_depth;
829 if (!continue_p(verbose))
830 return;
832 if (var != NULL && var_clock(var) == cur_clock)
833 dont_descend = 1;
835 if (var == NULL && is_lisp_pointer(obj))
836 var = define_var(NULL, obj, 0);
838 if (var != NULL)
839 var_setclock(var, cur_clock);
841 void (**fns)(lispobj) = NULL;
842 cur_depth++;
843 if (verbose) {
844 if (var != NULL) {
845 sprintf(buffer, "$%s=", var_name(var));
846 newline(buffer);
848 else
849 newline(NULL);
850 printf("%s0x%08lx: ", prefix, (unsigned long) obj);
851 if (cur_depth < brief_depth) {
852 fputs(lowtag_names[type], stdout);
853 fns = verbose_fns;
855 else
856 fns = brief_fns;
858 else {
859 if (dont_descend)
860 printf("$%s", var_name(var));
861 else {
862 if (var != NULL)
863 printf("$%s=", var_name(var));
864 fns = brief_fns;
867 if (!fns)
869 else if (is_lisp_pointer(obj) && !gc_managed_addr_p(obj))
870 printf("(bad-address)");
871 else
872 (*fns[type])(obj);
873 cur_depth--;
874 dont_descend = 0;
877 void reset_printer()
879 cur_clock++;
880 cur_lines = 0;
881 dont_descend = 0;
884 void print(lispobj obj)
886 skip_newline = 1;
887 cur_depth = 0;
888 max_depth = 5;
889 max_lines = 20;
891 print_obj("", obj);
893 putchar('\n');
896 void brief_print(lispobj obj)
898 skip_newline = 1;
899 cur_depth = 0;
900 max_depth = 1;
901 max_lines = 5000;
902 cur_lines = 0;
904 print_obj("", obj);
905 putchar('\n');
908 // The following accessors, which take a valid native pointer as input
909 // and return a Lisp string, are designed to be foolproof during GC,
910 // hence all the forwarding checks.
912 #include "forwarding-ptr.h"
913 #include "genesis/classoid.h"
914 struct vector * symbol_name(lispobj * sym)
916 if (forwarding_pointer_p(sym))
917 sym = native_pointer(forwarding_pointer_value(sym));
918 if (lowtag_of(((struct symbol*)sym)->name) != OTHER_POINTER_LOWTAG)
919 return NULL;
920 lispobj * name = native_pointer(((struct symbol*)sym)->name);
921 if (forwarding_pointer_p(name))
922 name = native_pointer(forwarding_pointer_value(name));
923 return (struct vector*)name;
925 struct vector * classoid_name(lispobj * classoid)
927 if (forwarding_pointer_p(classoid))
928 classoid = native_pointer(forwarding_pointer_value(classoid));
929 lispobj sym = ((struct classoid*)classoid)->name;
930 return lowtag_of(sym) != OTHER_POINTER_LOWTAG ? NULL
931 : symbol_name(native_pointer(sym));
933 struct vector * layout_classoid_name(lispobj * layout)
935 if (forwarding_pointer_p(layout))
936 layout = native_pointer(forwarding_pointer_value(layout));
937 lispobj classoid = ((struct layout*)layout)->classoid;
938 return lowtag_of(classoid) != INSTANCE_POINTER_LOWTAG ? NULL
939 : classoid_name(native_pointer(classoid));
941 struct vector * instance_classoid_name(lispobj * instance)
943 if (forwarding_pointer_p(instance))
944 instance = native_pointer(forwarding_pointer_value(instance));
945 lispobj layout = instance_layout(instance);
946 return lowtag_of(layout) != INSTANCE_POINTER_LOWTAG ? NULL
947 : layout_classoid_name(native_pointer(layout));
949 void safely_show_lstring(struct vector * string, int quotes, FILE *s)
951 extern void show_lstring(struct vector*, int, FILE*);
952 if (forwarding_pointer_p((lispobj*)string))
953 string = (struct vector*)forwarding_pointer_value((lispobj*)string);
954 if (
955 #ifdef SIMPLE_CHARACTER_STRING_WIDETAG
956 widetag_of(string->header) == SIMPLE_CHARACTER_STRING_WIDETAG ||
957 #endif
958 widetag_of(string->header) == SIMPLE_BASE_STRING_WIDETAG)
959 show_lstring(string, quotes, s);
960 else {
961 fprintf(s, "#<[widetag=%02X]>", widetag_of(string->header));