Take pointer, not word count, as upper limit in verify_space()
[sbcl.git] / src / runtime / print.c
blob9d7eef0b27cabf5d6942c8277aa52d0b3f44fc2f
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 (the various
17 * foo_slots[], at least) is deeply broken, depending on guessing
18 * already out-of-date values instead of getting them from sbcl.h.
21 #include <stdio.h>
22 #include <string.h>
24 #include "sbcl.h"
25 #include "print.h"
26 #include "runtime.h"
27 #include "gc-internal.h"
28 #include <stdarg.h>
29 #include "thread.h" /* genesis/primitive-objects.h needs this */
30 #include <errno.h>
31 #include <stdlib.h>
33 /* FSHOW and odxprint provide debugging output for low-level information
34 * (signal handling, exceptions, safepoints) which is hard to debug by
35 * other means.
37 * If enabled at all, environment variables control whether calls of the
38 * form odxprint(name, ...) are enabled at run-time, e.g. using
39 * SBCL_DYNDEBUG="fshow fshow_signal safepoints".
41 * In the case of FSHOW and FSHOW_SIGNAL, old-style code from runtime.h
42 * can also be used to enable or disable these more aggressively.
45 struct dyndebug_config dyndebug_config = {
46 QSHOW == 2, QSHOW_SIGNALS == 2
49 void
50 dyndebug_init()
52 #define DYNDEBUG_NFLAGS (sizeof(struct dyndebug_config) / sizeof(int))
53 #define dyndebug_init1(lowercase, uppercase) \
54 do { \
55 int *ptr = &dyndebug_config.dyndebug_##lowercase; \
56 ptrs[n] = ptr; \
57 names[n] = #lowercase; \
58 char *val = getenv("SBCL_DYNDEBUG__" uppercase); \
59 *ptr = val && strlen(val); \
60 n++; \
61 } while (0)
62 int n = 0;
63 char *names[DYNDEBUG_NFLAGS];
64 int *ptrs[DYNDEBUG_NFLAGS];
66 dyndebug_init1(fshow, "FSHOW");
67 dyndebug_init1(fshow_signal, "FSHOW_SIGNAL");
68 dyndebug_init1(gencgc_verbose, "GENCGC_VERBOSE");
69 dyndebug_init1(safepoints, "SAFEPOINTS");
70 dyndebug_init1(seh, "SEH");
71 dyndebug_init1(misc, "MISC");
72 dyndebug_init1(pagefaults, "PAGEFAULTS");
73 dyndebug_init1(io, "IO");
74 dyndebug_init1(runtime_link, "RUNTIME_LINK");
76 int n_output_flags = n;
77 dyndebug_init1(backtrace_when_lost, "BACKTRACE_WHEN_LOST");
78 dyndebug_init1(sleep_when_lost, "SLEEP_WHEN_LOST");
80 if (n != DYNDEBUG_NFLAGS)
81 fprintf(stderr, "Bug in dyndebug_init\n");
83 #if defined(LISP_FEATURE_GENCGC)
84 gencgc_verbose = dyndebug_config.dyndebug_gencgc_verbose;
85 #endif
87 char *featurelist = getenv("SBCL_DYNDEBUG");
88 if (featurelist) {
89 int err = 0;
90 featurelist = strdup(featurelist);
91 char *ptr = featurelist;
92 for (;;) {
93 char *token = strtok(ptr, " ");
94 if (!token) break;
95 int i;
96 if (!strcmp(token, "all"))
97 for (i = 0; i < n_output_flags; i++)
98 *ptrs[i] = 1;
99 else {
100 for (i = 0; i < (int)DYNDEBUG_NFLAGS; i++)
101 if (!strcmp(token, names[i])) {
102 *ptrs[i] = 1;
103 break;
105 if (i == DYNDEBUG_NFLAGS) {
106 fprintf(stderr, "No such dyndebug flag: `%s'\n", token);
107 err = 1;
110 ptr = 0;
112 free(featurelist);
113 if (err) {
114 fprintf(stderr, "Valid flags are:\n");
115 fprintf(stderr, " all ;enables all of the following:\n");
116 int i;
117 for (i = 0; i < (int)DYNDEBUG_NFLAGS; i++) {
118 if (i == n_output_flags)
119 fprintf(stderr, "Additional options:\n");
120 fprintf(stderr, " %s\n", names[i]);
125 #undef dyndebug_init1
126 #undef DYNDEBUG_NFLAGS
129 /* Temporarily, odxprint merely performs the equivalent of a traditional
130 * FSHOW call, i.e. it merely formats to stderr. Ultimately, it should
131 * be restored to its full win32 branch functionality, where output to a
132 * file or to the debugger can be selected at runtime. */
134 void vodxprint_fun(const char *, va_list);
136 void
137 odxprint_fun(const char *fmt, ...)
139 va_list args;
140 va_start(args, fmt);
141 vodxprint_fun(fmt, args);
142 va_end(args);
145 void
146 vodxprint_fun(const char *fmt, va_list args)
148 #ifdef LISP_FEATURE_WIN32
149 DWORD lastError = GetLastError();
150 #endif
151 int original_errno = errno;
153 QSHOW_BLOCK;
155 char buf[1024];
156 int n = 0;
158 #ifdef LISP_FEATURE_SB_THREAD
159 struct thread *arch_os_get_current_thread(void);
160 struct thread *self = arch_os_get_current_thread();
161 void *pth = self ? (void *) self->os_thread : 0;
162 snprintf(buf, sizeof(buf), "[%p/%p] ", self, pth);
163 n = strlen(buf);
164 #endif
166 vsnprintf(buf + n, sizeof(buf) - n - 1, fmt, args);
167 /* buf is now zero-terminated (even in case of overflow).
168 * Our caller took care of the newline (if any) through `fmt'. */
170 /* A sufficiently POSIXy implementation of stdio will provide
171 * per-FILE locking, as defined in the spec for flockfile. At least
172 * glibc complies with this. Hence we do not need to perform
173 * locking ourselves here. (Should it turn out, of course, that
174 * other libraries opt for speed rather than safety, we need to
175 * revisit this decision.) */
176 fputs(buf, stderr);
178 #ifdef LISP_FEATURE_WIN32
179 /* stdio's stderr is line-bufferred, i.e. \n ought to flush it.
180 * Unfortunately, MinGW does not behave the way I would expect it
181 * to. Let's be safe: */
182 fflush(stderr);
183 #endif
185 QSHOW_UNBLOCK;
187 #ifdef LISP_FEATURE_WIN32
188 SetLastError(lastError);
189 #endif
190 errno = original_errno;
193 /* Translate the rather awkward syntax
194 * FSHOW((stderr, "xyz"))
195 * into the new and cleaner
196 * odxprint("xyz").
197 * If we were willing to clean up all existing call sites, we could remove
198 * this wrapper function. (This is a function, because I don't know how to
199 * strip the extra parens in a macro.) */
200 void
201 fshow_fun(void __attribute__((__unused__)) *ignored,
202 const char *fmt,
203 ...)
205 va_list args;
206 va_start(args, fmt);
207 vodxprint_fun(fmt, args);
208 va_end(args);
211 /* This file can be skipped if we're not supporting LDB. */
212 #if defined(LISP_FEATURE_SB_LDB)
214 #include "monitor.h"
215 #include "vars.h"
216 #include "os.h"
217 #ifdef LISP_FEATURE_GENCGC
218 #include "gencgc-alloc-region.h" /* genesis/thread.h needs this */
219 #endif
220 #if defined(LISP_FEATURE_WIN32)
221 # include "win32-thread-private-events.h" /* genesis/thread.h needs this */
222 #endif
223 #include "genesis/static-symbols.h"
224 #include "genesis/primitive-objects.h"
225 #include "genesis/static-symbols.h"
226 #include "genesis/tagnames.h"
228 static int max_lines = 20, cur_lines = 0;
229 static int max_depth = 5, brief_depth = 2, cur_depth = 0;
230 static int max_length = 5;
231 static boolean dont_descend = 0, skip_newline = 0;
232 static int cur_clock = 0;
234 static void print_obj(char *prefix, lispobj obj);
236 #define NEWLINE_OR_RETURN if (continue_p(1)) newline(NULL); else return;
238 static void indent(int in)
240 static char *spaces = " ";
242 while (in > 64) {
243 fputs(spaces, stdout);
244 in -= 64;
246 if (in != 0)
247 fputs(spaces + 64 - in, stdout);
250 static boolean continue_p(boolean newline)
252 char buffer[256];
254 if (cur_depth >= max_depth || dont_descend)
255 return 0;
257 if (newline) {
258 if (skip_newline)
259 skip_newline = 0;
260 else
261 putchar('\n');
263 if (cur_lines >= max_lines) {
264 printf("More? [y] ");
265 fflush(stdout);
267 if (fgets(buffer, sizeof(buffer), stdin)) {
268 if (buffer[0] == 'n' || buffer[0] == 'N')
269 throw_to_monitor();
270 else
271 cur_lines = 0;
272 } else {
273 printf("\nUnable to read response, assuming y.\n");
274 cur_lines = 0;
279 return 1;
282 static void newline(char *label)
284 cur_lines++;
285 if (label != NULL)
286 fputs(label, stdout);
287 putchar('\t');
288 indent(cur_depth * 2);
292 static void print_unknown(lispobj obj)
294 printf("unknown object: %p", (void *)obj);
297 static void brief_fixnum(lispobj obj)
299 /* KLUDGE: Rather than update the tables in print_obj(), we
300 declare all fixnum-or-unknown tags to be fixnums and sort it
301 out here with a guard clause. */
302 if (!fixnump(obj)) return print_unknown(obj);
304 #ifndef LISP_FEATURE_ALPHA
305 printf("%ld", ((long)obj)>>N_FIXNUM_TAG_BITS);
306 #else
307 printf("%d", ((s32)obj)>>N_FIXNUM_TAG_BITS);
308 #endif
311 static void print_fixnum(lispobj obj)
313 /* KLUDGE: Rather than update the tables in print_obj(), we
314 declare all fixnum-or-unknown tags to be fixnums and sort it
315 out here with a guard clause. */
316 if (!fixnump(obj)) return print_unknown(obj);
318 #ifndef LISP_FEATURE_ALPHA
319 printf(": %ld", ((long)obj)>>N_FIXNUM_TAG_BITS);
320 #else
321 printf(": %d", ((s32)obj)>>N_FIXNUM_TAG_BITS);
322 #endif
325 static void brief_otherimm(lispobj obj)
327 int type, c;
328 char * charname = 0;
330 type = widetag_of(obj);
331 switch (type) {
332 case CHARACTER_WIDETAG:
333 c = obj>>8; // no mask. show whatever's there
334 printf("#\\");
335 switch (c) {
336 case '\0': charname = "Nul"; break;
337 case '\n': charname = "Newline"; break;
338 case '\b': charname = "Backspace"; break;
339 case '\177': charname = "Delete"; break;
340 default:
341 if (c < 32) printf("^%c", c+64);
342 else printf(c < 128 ? "%c" : "U+%X", c);
344 if (charname)
345 fputs(charname, stdout);
346 break;
348 case UNBOUND_MARKER_WIDETAG:
349 printf("<unbound marker>");
350 break;
352 default:
353 printf("%s", widetag_names[type >> 2]);
354 break;
358 static void print_otherimm(lispobj obj)
360 printf(", %s", widetag_names[widetag_of(obj) >> 2]);
362 switch (widetag_of(obj)) {
363 case CHARACTER_WIDETAG:
364 printf(": ");
365 brief_otherimm(obj);
366 break;
368 case SAP_WIDETAG:
369 case UNBOUND_MARKER_WIDETAG:
370 break;
372 default:
373 printf(": data=%"OBJ_FMTX, (obj>>8));
374 break;
378 static void brief_list(lispobj obj)
380 int space = 0;
381 int length = 0;
383 if (!is_valid_lisp_addr((os_vm_address_t)native_pointer(obj)))
384 printf("(invalid Lisp-level address)");
385 else if (obj == NIL)
386 printf("NIL");
387 else {
388 putchar('(');
389 while (lowtag_of(obj) == LIST_POINTER_LOWTAG) {
390 struct cons *cons = (struct cons *)native_pointer(obj);
392 if (space)
393 putchar(' ');
394 if (++length >= max_length) {
395 printf("...");
396 obj = NIL;
397 break;
399 print_obj("", cons->car);
400 obj = cons->cdr;
401 space = 1;
402 if (obj == NIL)
403 break;
405 if (obj != NIL) {
406 printf(" . ");
407 print_obj("", obj);
409 putchar(')');
413 static void print_list(lispobj obj)
415 if (!is_valid_lisp_addr((os_vm_address_t)native_pointer(obj))) {
416 printf("(invalid address)");
417 } else if (obj == NIL) {
418 printf(" (NIL)");
419 } else {
420 struct cons *cons = (struct cons *)native_pointer(obj);
422 print_obj("car: ", cons->car);
423 print_obj("cdr: ", cons->cdr);
427 // takes native pointer as input
428 char * simple_base_stringize(struct vector * string)
430 if (widetag_of(string->header) == SIMPLE_BASE_STRING_WIDETAG)
431 return (char*)string->data;
432 int length = string->length;
433 char * newstring = malloc(length+1);
434 uint32_t * data = (uint32_t*)string->data;
435 int i;
436 for(i=0;i<length;++i)
437 newstring[i] = data[i] < 128 ? data[i] : '?';
438 newstring[length] = 0;
439 return newstring;
442 static void brief_struct(lispobj obj)
444 struct instance *instance = (struct instance *)native_pointer(obj);
445 if (!is_valid_lisp_addr((os_vm_address_t)instance)) {
446 printf("(invalid address)");
447 } else {
448 extern struct vector * instance_classoid_name(lispobj*);
449 struct vector * classoid_name;
450 classoid_name = instance_classoid_name((lispobj*)instance);
451 if ( classoid_name ) {
452 char * namestring = simple_base_stringize(classoid_name);
453 printf("#<ptr to %p %s instance>",
454 (void*)instance_layout((lispobj*)instance), namestring);
455 if ( namestring != (char*)classoid_name->data )
456 free(namestring);
457 } else {
458 printf("#<ptr to %p instance>",
459 (void*)instance_layout((lispobj*)instance));
464 #include "genesis/layout.h"
465 static boolean tagged_slot_p(struct layout * layout,
466 int slot_index)
468 lispobj bitmap = layout->bitmap;
469 sword_t fixnum = (sword_t)bitmap >> N_FIXNUM_TAG_BITS; // optimistically
470 return fixnump(bitmap)
471 ? bitmap == make_fixnum(-1) ||
472 (slot_index < N_WORD_BITS && ((fixnum >> slot_index) & 1) != 0)
473 : positive_bignum_logbitp(slot_index,
474 (struct bignum*)native_pointer(bitmap));
477 static void print_struct(lispobj obj)
479 struct instance *instance = (struct instance *)native_pointer(obj);
480 unsigned int i;
481 char buffer[16];
482 if (!is_valid_lisp_addr((os_vm_address_t)instance)) {
483 printf("(invalid address)");
484 } else {
485 lispobj layout_obj = instance_layout(native_pointer(obj));
486 print_obj("type: ", layout_obj);
487 struct layout * layout = (struct layout*)native_pointer(layout_obj);
488 for (i=INSTANCE_DATA_START; i<instance_length(instance->header); i++) {
489 sprintf(buffer, "slot %d: ", i);
490 if (layout != NULL && tagged_slot_p(layout, i)) {
491 print_obj(buffer, instance->slots[i]);
492 } else {
493 newline(NULL);
494 printf("\n\t %s0x%"OBJ_FMTX" [raw]", buffer, instance->slots[i]);
500 void show_lstring(struct vector * string, int quotes, FILE *s)
502 int ucs4_p = 0;
503 int i, len = fixnum_value(string->length);
505 #ifdef SIMPLE_CHARACTER_STRING_WIDETAG
506 if (widetag_of(string->header) == SIMPLE_CHARACTER_STRING_WIDETAG) {
507 ucs4_p = 1;
508 if (quotes)
509 putc('u', s); /* an arbitrary notational convention */
511 #endif
512 if (quotes) putc('"', s);
513 for (i=0 ; i<len ; i++) {
514 // hopefully the compiler will optimize out the ucs4_p test
515 // when the runtime is built without Unicode support
516 int ch;
517 if (ucs4_p)
518 ch = i[(uint32_t*)string->data];
519 else
520 ch = i[(char*)string->data];
521 if (ch >= 32 && ch < 127) {
522 if (quotes && (ch == '"' || ch == '\\'))
523 putc('\\', s);
524 putc(ch, s);
525 } else {
526 fprintf(s, ch > 0xffff ? "\\U%08X" :
527 ch > 0xff ? "\\u%04X" : "\\x%02X", ch);
530 if (quotes) putc('"', s);
533 static void brief_otherptr(lispobj obj)
535 extern void safely_show_lstring(struct vector*, int, FILE*);
536 lispobj *ptr, header;
537 int type;
538 struct symbol *symbol;
540 ptr = native_pointer(obj);
542 if (!is_valid_lisp_addr((os_vm_address_t)obj)) {
543 printf("(invalid address)");
544 return;
547 header = *ptr;
548 type = widetag_of(header);
549 switch (type) {
550 case SYMBOL_HEADER_WIDETAG:
551 symbol = (struct symbol *)ptr;
552 if (symbol->package == NIL)
553 printf("#:");
554 show_lstring((struct vector *)native_pointer(symbol->name),
555 0, stdout);
556 break;
558 case SIMPLE_BASE_STRING_WIDETAG:
559 #ifdef SIMPLE_CHARACTER_STRING_WIDETAG
560 case SIMPLE_CHARACTER_STRING_WIDETAG:
561 #endif
562 show_lstring((struct vector*)ptr, 1, stdout);
563 break;
565 default:
566 printf("#<ptr to ");
567 brief_otherimm(header);
568 if (type == FDEFN_WIDETAG) { // Try to print name, if a symbol
569 // FIXME: more address validity checks perhaps?
570 lispobj name = ((struct fdefn*)ptr)->name;
571 if (lowtag_of(name) == OTHER_POINTER_LOWTAG
572 && widetag_of(*native_pointer(name)) == SYMBOL_HEADER_WIDETAG) {
573 printf(" for ");
574 struct vector* str = symbol_name(native_pointer(name));
575 safely_show_lstring(str, 0, stdout);
578 putchar('>');
582 static void print_slots(char **slots, int count, lispobj *ptr)
584 while (count-- > 0) {
585 if (*slots) {
586 print_obj(*slots++, *ptr++);
587 } else {
588 print_obj("???: ", *ptr++);
593 /* FIXME: Yikes! This needs to depend on the values in sbcl.h (or
594 * perhaps be generated automatically by GENESIS as part of
595 * sbcl.h). */
596 static char *symbol_slots[] = {"value: ", "hash: ",
597 "info: ", "name: ", "package: ",
598 #if defined (LISP_FEATURE_SB_THREAD) && !defined(LISP_FEATURE_X86_64)
599 "tls-index: " ,
600 #endif
601 NULL};
602 static char *ratio_slots[] = {"numer: ", "denom: ", NULL};
603 static char *complex_slots[] = {"real: ", "imag: ", NULL};
604 static char *code_slots[] = {"bytes: ", "debug: ",
605 #ifndef LISP_FEATURE_64_BIT
606 "n_entries: ",
607 #endif
608 NULL};
609 static char *simple_fun_slots[] = {
610 "self: ", "name: ", "arglist: ", "type: ", "info: ", NULL};
611 static char *closure_slots[] = {"fn: ", NULL};
612 static char *funcallable_instance_slots[] = {"raw_fn: ", "fn: ",
613 #ifndef LISP_FEATURE_COMPACT_INSTANCE_HEADER
614 "layout: ",
615 #endif
616 NULL};
617 static char *weak_pointer_slots[] = {"value: ", NULL};
618 static char *fdefn_slots[] = {"name: ", "function: ", "raw_addr: ", NULL};
619 static char *value_cell_slots[] = {"value: ", NULL};
621 static lispobj symbol_function(lispobj* symbol)
623 lispobj info = ((struct symbol*)symbol)->info;
624 if (lowtag_of(info) == LIST_POINTER_LOWTAG)
625 info = CONS(info)->cdr;
626 if (lowtag_of(info) == OTHER_POINTER_LOWTAG) {
627 struct vector* v = (struct vector*)native_pointer(info);
628 int len = fixnum_value(v->length);
629 if (len != 0) {
630 lispobj elt = v->data[0]; // Just like INFO-VECTOR-FDEFN
631 if (fixnump(elt) && (fixnum_value(elt) & 07777) >= 07701) {
632 lispobj fdefn = v->data[len-1];
633 if (lowtag_of(fdefn) == OTHER_POINTER_LOWTAG)
634 return FDEFN(fdefn)->fun;
638 return NIL;
641 static void print_otherptr(lispobj obj)
643 if (!is_valid_lisp_addr((os_vm_address_t)obj)) {
644 printf("(invalid address)");
645 } else {
646 #ifndef LISP_FEATURE_ALPHA
647 lispobj *ptr;
648 unsigned long header;
649 unsigned long length;
650 #else
651 u32 *ptr;
652 u32 header;
653 u32 length;
654 #endif
655 int count, type, index;
656 char buffer[16];
658 ptr = native_pointer(obj);
659 if (ptr == NULL) {
660 printf(" (NULL Pointer)");
661 return;
664 header = *ptr++;
665 length = fixnum_value(*ptr);
666 count = HeaderValue(header);
667 type = widetag_of(header);
669 print_obj("header: ", header);
670 if (!other_immediate_lowtag_p(header)) {
671 NEWLINE_OR_RETURN;
672 printf("(invalid header object)");
673 return;
676 if (unprintable_array_types[type/8] & (1<<(type % 8)))
677 return;
678 switch (type) {
679 case BIGNUM_WIDETAG:
680 ptr += count;
681 NEWLINE_OR_RETURN;
682 printf("0x");
683 while (count-- > 0)
684 printf(
685 #if N_WORD_BITS == 32
686 "%08lx%s",
687 #else
688 "%016lx%s",
689 #endif
690 (unsigned long) *--ptr, (count?"_":""));
691 break;
693 case RATIO_WIDETAG:
694 print_slots(ratio_slots, count, ptr);
695 break;
697 case COMPLEX_WIDETAG:
698 print_slots(complex_slots, count, ptr);
699 break;
701 case SYMBOL_HEADER_WIDETAG:
702 // Only 1 byte of a symbol header conveys its size.
703 // The other bytes may be freely used by the backend.
704 print_slots(symbol_slots, count & 0xFF, ptr);
705 if (symbol_function(ptr-1) != NIL)
706 print_obj("fun: ", symbol_function(ptr-1));
707 break;
709 #if N_WORD_BITS == 32
710 case SINGLE_FLOAT_WIDETAG:
711 NEWLINE_OR_RETURN;
712 printf("%g", ((struct single_float *)native_pointer(obj))->value);
713 break;
714 #endif
715 case DOUBLE_FLOAT_WIDETAG:
716 NEWLINE_OR_RETURN;
717 printf("%g", ((struct double_float *)native_pointer(obj))->value);
718 break;
720 #ifdef LONG_FLOAT_WIDETAG
721 case LONG_FLOAT_WIDETAG:
722 NEWLINE_OR_RETURN;
723 printf("%Lg", ((struct long_float *)native_pointer(obj))->value);
724 break;
725 #endif
727 #ifdef COMPLEX_SINGLE_FLOAT_WIDETAG
728 case COMPLEX_SINGLE_FLOAT_WIDETAG:
729 NEWLINE_OR_RETURN;
730 #ifdef LISP_FEATURE_64_BIT
731 printf("%g", ((struct complex_single_float *)native_pointer(obj))->data.data[0]);
732 #else
733 printf("%g", ((struct complex_single_float *)native_pointer(obj))->real);
734 #endif
735 NEWLINE_OR_RETURN;
736 #ifdef LISP_FEATURE_64_BIT
737 printf("%g", ((struct complex_single_float *)native_pointer(obj))->data.data[1]);
738 #else
739 printf("%g", ((struct complex_single_float *)native_pointer(obj))->imag);
740 #endif
741 break;
742 #endif
744 #ifdef COMPLEX_DOUBLE_FLOAT_WIDETAG
745 case COMPLEX_DOUBLE_FLOAT_WIDETAG:
746 NEWLINE_OR_RETURN;
747 printf("%g", ((struct complex_double_float *)native_pointer(obj))->real);
748 NEWLINE_OR_RETURN;
749 printf("%g", ((struct complex_double_float *)native_pointer(obj))->imag);
750 break;
751 #endif
753 #ifdef COMPLEX_LONG_FLOAT_WIDETAG
754 case COMPLEX_LONG_FLOAT_WIDETAG:
755 NEWLINE_OR_RETURN;
756 printf("%Lg", ((struct complex_long_float *)native_pointer(obj))->real);
757 NEWLINE_OR_RETURN;
758 printf("%Lg", ((struct complex_long_float *)native_pointer(obj))->imag);
759 break;
760 #endif
762 case SIMPLE_BASE_STRING_WIDETAG:
763 #ifdef SIMPLE_CHARACTER_STRING_WIDETAG
764 case SIMPLE_CHARACTER_STRING_WIDETAG:
765 #endif
766 NEWLINE_OR_RETURN;
767 show_lstring((struct vector*)native_pointer(obj), 1, stdout);
768 break;
770 case SIMPLE_VECTOR_WIDETAG:
771 NEWLINE_OR_RETURN;
772 printf("length = %ld", length);
773 ptr++;
774 index = 0;
775 while (length-- > 0) {
776 sprintf(buffer, "%d: ", index++);
777 print_obj(buffer, *ptr++);
779 break;
781 // FIXME: This case looks unreachable. print_struct() does it
782 case INSTANCE_HEADER_WIDETAG:
783 NEWLINE_OR_RETURN;
784 count &= SHORT_HEADER_MAX_WORDS;
785 printf("length = %ld", (long) count);
786 index = 0;
787 while (count-- > 0) {
788 sprintf(buffer, "%d: ", index++);
789 print_obj(buffer, *ptr++);
791 break;
793 case CODE_HEADER_WIDETAG:
794 count &= SHORT_HEADER_MAX_WORDS;
795 // ptr was already bumped up
796 for_each_simple_fun(fun_index, fun, (struct code*)(ptr-1), 0, {
797 sprintf(buffer, "f[%d]: ", fun_index);
798 print_obj(buffer, make_lispobj(fun,FUN_POINTER_LOWTAG));
800 print_slots(code_slots, count-1, ptr);
801 break;
803 case SIMPLE_FUN_HEADER_WIDETAG:
804 print_obj("code: ",
805 make_lispobj(native_pointer((lispobj)(ptr-1))
806 -(HeaderValue(header)&0xFFFF),
807 OTHER_POINTER_LOWTAG));
808 print_slots(simple_fun_slots,
809 sizeof simple_fun_slots/sizeof(char*)-1, ptr);
810 break;
812 #if !defined(LISP_FEATURE_X86) && !defined(LISP_FEATURE_X86_64)
813 case RETURN_PC_HEADER_WIDETAG:
814 print_obj("code: ", obj - (count * 4));
815 break;
816 #endif
818 case CLOSURE_HEADER_WIDETAG:
819 print_slots(closure_slots,
820 count & SHORT_HEADER_MAX_WORDS, ptr);
821 break;
823 case FUNCALLABLE_INSTANCE_HEADER_WIDETAG:
824 print_slots(funcallable_instance_slots,
825 count & SHORT_HEADER_MAX_WORDS, ptr);
826 break;
828 case VALUE_CELL_HEADER_WIDETAG:
829 print_slots(value_cell_slots, 1, ptr);
830 break;
832 case SAP_WIDETAG:
833 NEWLINE_OR_RETURN;
834 #ifndef LISP_FEATURE_ALPHA
835 printf("0x%08lx", (unsigned long) *ptr);
836 #else
837 printf("0x%016lx", *(lispobj*)(ptr+1));
838 #endif
839 break;
841 case WEAK_POINTER_WIDETAG:
842 print_slots(weak_pointer_slots, 1, ptr);
843 break;
845 case CHARACTER_WIDETAG:
846 case UNBOUND_MARKER_WIDETAG:
847 NEWLINE_OR_RETURN;
848 printf("pointer to an immediate?");
849 break;
851 case FDEFN_WIDETAG:
852 #ifdef LISP_FEATURE_IMMOBILE_CODE
853 print_slots(fdefn_slots, 2, ptr);
854 print_obj("entry: ", fdefn_raw_referent((struct fdefn*)(ptr-1)));
855 #else
856 print_slots(fdefn_slots, count & SHORT_HEADER_MAX_WORDS, ptr);
857 #endif
858 break;
860 default:
861 NEWLINE_OR_RETURN;
862 printf("Unknown header object?");
863 break;
868 static void print_obj(char *prefix, lispobj obj)
870 #ifdef LISP_FEATURE_64_BIT
871 static void (*verbose_fns[])(lispobj obj)
872 = {print_fixnum, print_otherimm, print_fixnum, print_struct,
873 print_fixnum, print_otherimm, print_fixnum, print_list,
874 print_fixnum, print_otherimm, print_fixnum, print_otherptr,
875 print_fixnum, print_otherimm, print_fixnum, print_otherptr};
876 static void (*brief_fns[])(lispobj obj)
877 = {brief_fixnum, brief_otherimm, brief_fixnum, brief_struct,
878 brief_fixnum, brief_otherimm, brief_fixnum, brief_list,
879 brief_fixnum, brief_otherimm, brief_fixnum, brief_otherptr,
880 brief_fixnum, brief_otherimm, brief_fixnum, brief_otherptr};
881 #else
882 static void (*verbose_fns[])(lispobj obj)
883 = {print_fixnum, print_struct, print_otherimm, print_list,
884 print_fixnum, print_otherptr, print_otherimm, print_otherptr};
885 static void (*brief_fns[])(lispobj obj)
886 = {brief_fixnum, brief_struct, brief_otherimm, brief_list,
887 brief_fixnum, brief_otherptr, brief_otherimm, brief_otherptr};
888 #endif
889 int type = lowtag_of(obj);
890 struct var *var = lookup_by_obj(obj);
891 char buffer[256];
892 boolean verbose = cur_depth < brief_depth;
894 if (!continue_p(verbose))
895 return;
897 if (var != NULL && var_clock(var) == cur_clock)
898 dont_descend = 1;
900 if (var == NULL && is_lisp_pointer(obj))
901 var = define_var(NULL, obj, 0);
903 if (var != NULL)
904 var_setclock(var, cur_clock);
906 cur_depth++;
907 if (verbose) {
908 if (var != NULL) {
909 sprintf(buffer, "$%s=", var_name(var));
910 newline(buffer);
912 else
913 newline(NULL);
914 printf("%s0x%08lx: ", prefix, (unsigned long) obj);
915 if (cur_depth < brief_depth) {
916 fputs(lowtag_names[type], stdout);
917 (*verbose_fns[type])(obj);
919 else
920 (*brief_fns[type])(obj);
922 else {
923 if (dont_descend)
924 printf("$%s", var_name(var));
925 else {
926 if (var != NULL)
927 printf("$%s=", var_name(var));
928 (*brief_fns[type])(obj);
931 cur_depth--;
932 dont_descend = 0;
935 void reset_printer()
937 cur_clock++;
938 cur_lines = 0;
939 dont_descend = 0;
942 void print(lispobj obj)
944 skip_newline = 1;
945 cur_depth = 0;
946 max_depth = 5;
947 max_lines = 20;
949 print_obj("", obj);
951 putchar('\n');
954 void brief_print(lispobj obj)
956 skip_newline = 1;
957 cur_depth = 0;
958 max_depth = 1;
959 max_lines = 5000;
960 cur_lines = 0;
962 print_obj("", obj);
963 putchar('\n');
966 // The following accessors, which take a valid native pointer as input
967 // and return a Lisp string, are designed to be foolproof during GC,
968 // hence all the forwarding checks.
970 #include "forwarding-ptr.h"
971 #include "genesis/classoid.h"
972 struct vector * symbol_name(lispobj * sym)
974 if (forwarding_pointer_p(sym))
975 sym = native_pointer(forwarding_pointer_value(sym));
976 if (lowtag_of(((struct symbol*)sym)->name) != OTHER_POINTER_LOWTAG)
977 return NULL;
978 lispobj * name = native_pointer(((struct symbol*)sym)->name);
979 if (forwarding_pointer_p(name))
980 name = native_pointer(forwarding_pointer_value(name));
981 return (struct vector*)name;
983 struct vector * classoid_name(lispobj * classoid)
985 if (forwarding_pointer_p(classoid))
986 classoid = native_pointer(forwarding_pointer_value(classoid));
987 lispobj sym = ((struct classoid*)classoid)->name;
988 return lowtag_of(sym) != OTHER_POINTER_LOWTAG ? NULL
989 : symbol_name(native_pointer(sym));
991 struct vector * layout_classoid_name(lispobj * layout)
993 if (forwarding_pointer_p(layout))
994 layout = native_pointer(forwarding_pointer_value(layout));
995 lispobj classoid = ((struct layout*)layout)->classoid;
996 return lowtag_of(classoid) != INSTANCE_POINTER_LOWTAG ? NULL
997 : classoid_name(native_pointer(classoid));
999 struct vector * instance_classoid_name(lispobj * instance)
1001 if (forwarding_pointer_p(instance))
1002 instance = native_pointer(forwarding_pointer_value(instance));
1003 lispobj layout = instance_layout(instance);
1004 return lowtag_of(layout) != INSTANCE_POINTER_LOWTAG ? NULL
1005 : layout_classoid_name(native_pointer(layout));
1007 void safely_show_lstring(struct vector * string, int quotes, FILE *s)
1009 extern void show_lstring(struct vector*, int, FILE*);
1010 if (forwarding_pointer_p((lispobj*)string))
1011 string = (struct vector*)forwarding_pointer_value((lispobj*)string);
1012 if (
1013 #ifdef SIMPLE_CHARACTER_STRING_WIDETAG
1014 widetag_of(string->header) == SIMPLE_CHARACTER_STRING_WIDETAG ||
1015 #endif
1016 widetag_of(string->header) == SIMPLE_BASE_STRING_WIDETAG)
1017 show_lstring(string, quotes, s);
1018 else {
1019 fprintf(s, "#<[widetag=%02X]>", widetag_of(string->header));
1023 #else
1025 void
1026 brief_print(lispobj obj)
1028 printf("lispobj 0x%lx\n", (unsigned long)obj);
1031 #endif /* defined(LISP_FEATURE_SB_LDB) */