0.pre7.109:
[sbcl.git] / src / runtime / print.c
1 /* code for low-level debugging/diagnostic output */
2
3 /*
4  * This software is part of the SBCL system. See the README file for
5  * more information.
6  *
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.
12  */
13
14 /*
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.
19  */
20
21 #include <stdio.h>
22
23 #include "print.h"
24 #include "runtime.h"
25 #include "sbcl.h"
26
27 /* This file can be skipped if we're not supporting LDB. */
28 #if defined(LISP_FEATURE_SB_LDB)
29
30 #include "sbcl.h"
31 #include "monitor.h"
32 #include "vars.h"
33 #include "os.h"
34
35 static int max_lines = 20, cur_lines = 0;
36 static int max_depth = 5, brief_depth = 2, cur_depth = 0;
37 static int max_length = 5;
38 static boolean dont_descend = 0, skip_newline = 0;
39 static int cur_clock = 0;
40
41 static void print_obj(char *prefix, lispobj obj);
42
43 #define NEWLINE_OR_RETURN if (continue_p(1)) newline(NULL); else return;
44
45 char *lowtag_Names[] = {
46     "even fixnum",
47     "function pointer",
48     "other immediate [0]",
49     "list pointer",
50     "odd fixnum",
51     "instance pointer",
52     "other immediate [1]",
53     "other pointer"
54 };
55
56 /* FIXME: Yikes! This table implicitly depends on the values in sbcl.h,
57  * but doesn't actually depend on them, so if they change, it gets
58  * all broken. We should either get rid of it or
59  * rewrite the code so that it's cleanly initialized by gc_init_tables[]
60  * in a way which varies correctly with the values in sbcl.h. */
61 char *subtype_Names[] = {
62     "unused 0",
63     "unused 1",
64     "bignum",
65     "ratio",
66     "single float",
67     "double float",
68 #ifdef LONG_FLOAT_WIDETAG
69     "long float",
70 #endif
71     "complex",
72 #ifdef COMPLEX_SINGLE_FLOAT_WIDETAG
73     "complex single float",
74 #endif
75 #ifdef COMPLEX_DOUBLE_FLOAT_WIDETAG
76     "complex double float",
77 #endif
78 #ifdef COMPLEX_LONG_FLOAT_WIDETAG
79     "complex long float",
80 #endif
81     "simple-array",
82     "simple-string",
83     "simple-bit-vector",
84     "simple-vector",
85     "(simple-array (unsigned-byte 2) (*))",
86     "(simple-array (unsigned-byte 4) (*))",
87     "(simple-array (unsigned-byte 8) (*))",
88     "(simple-array (unsigned-byte 16) (*))",
89     "(simple-array (unsigned-byte 32) (*))",
90 #ifdef SIMPLE_ARRAY_SIGNED_BYTE_8_WIDETAG
91     "(simple-array (signed-byte 8) (*))",
92 #endif
93 #ifdef SIMPLE_ARRAY_SIGNED_BYTE_16_WIDETAG
94     "(simple-array (signed-byte 16) (*))",
95 #endif
96 #ifdef SIMPLE_ARRAY_SIGNED_BYTE_30_WIDETAG
97     "(simple-array fixnum (*))",
98 #endif
99 #ifdef SIMPLE_ARRAY_SIGNED_BYTE_32_WIDETAG
100     "(simple-array (signed-byte 32) (*))",
101 #endif
102     "(simple-array single-float (*))",
103     "(simple-array double-float (*))",
104 #ifdef SIMPLE_ARRAY_LONG_FLOAT_WIDETAG
105     "(simple-array long-float (*))",
106 #endif
107 #ifdef SIMPLE_ARRAY_COMPLEX_SINGLE_FLOAT_WIDETAG
108     "(simple-array (complex single-float) (*))",
109 #endif
110 #ifdef SIMPLE_ARRAY_COMPLEX_DOUBLE_FLOAT_WIDETAG
111     "(simple-array (complex double-float) (*))",
112 #endif
113 #ifdef SIMPLE_ARRAY_COMPLEX_LONG_FLOAT_WIDETAG
114     "(simple-array (complex long-float) (*))",
115 #endif
116     "complex-string",
117     "complex-bit-vector",
118     "(array * (*))",
119     "array",
120     "code header",
121     "function header",
122     "closure header",
123     "funcallable-instance header",
124     "unused function header 1",
125     "unused function header 2",
126     "unused function header 3",
127     "closure function header",
128     "return PC header",
129     "value cell header",
130     "symbol header",
131     "character",
132     "SAP",
133     "unbound marker",
134     "weak pointer",
135     "instance header",
136     "fdefn"
137 };
138
139 static void indent(int in)
140 {
141     static char *spaces = "                                                                ";
142
143     while (in > 64) {
144         fputs(spaces, stdout);
145         in -= 64;
146     }
147     if (in != 0)
148         fputs(spaces + 64 - in, stdout);
149 }
150
151 static boolean continue_p(boolean newline)
152 {
153     char buffer[256];
154
155     if (cur_depth >= max_depth || dont_descend)
156         return 0;
157
158     if (newline) {
159         if (skip_newline)
160             skip_newline = 0;
161         else
162             putchar('\n');
163
164         if (cur_lines >= max_lines) {
165             printf("More? [y] ");
166             fflush(stdout);
167
168             fgets(buffer, sizeof(buffer), stdin);
169
170             if (buffer[0] == 'n' || buffer[0] == 'N')
171                 throw_to_monitor();
172             else
173                 cur_lines = 0;
174         }
175     }
176
177     return 1;
178 }
179
180 static void newline(char *label)
181 {
182     cur_lines++;
183     if (label != NULL)
184         fputs(label, stdout);
185     putchar('\t');
186     indent(cur_depth * 2);
187 }
188
189
190 static void brief_fixnum(lispobj obj)
191 {
192 #ifndef alpha
193     printf("%ld", ((long)obj)>>2);
194 #else
195     printf("%d", ((s32)obj)>>2);
196 #endif
197 }
198
199 static void print_fixnum(lispobj obj)
200 {
201 #ifndef alpha
202     printf(": %ld", ((long)obj)>>2);
203 #else
204     printf(": %d", ((s32)obj)>>2);
205 #endif
206 }
207
208 static void brief_otherimm(lispobj obj)
209 {
210     int type, c, idx;
211     char buffer[10];
212
213     type = widetag_of(obj);
214     switch (type) {
215         case BASE_CHAR_WIDETAG:
216             c = (obj>>8)&0xff;
217             switch (c) {
218                 case '\0':
219                     printf("#\\Null");
220                     break;
221                 case '\n':
222                     printf("#\\Newline");
223                     break;
224                 case '\b':
225                     printf("#\\Backspace");
226                     break;
227                 case '\177':
228                     printf("#\\Delete");
229                     break;
230                 default:
231                     strcpy(buffer, "#\\");
232                     if (c >= 128) {
233                         strcat(buffer, "m-");
234                         c -= 128;
235                     }
236                     if (c < 32) {
237                         strcat(buffer, "c-");
238                         c += '@';
239                     }
240                     printf("%s%c", buffer, c);
241                     break;
242             }
243             break;
244
245         case UNBOUND_MARKER_WIDETAG:
246             printf("<unbound marker>");
247             break;
248
249         default:
250             idx = type >> 2;
251             if (idx < (sizeof(lowtag_Names) / sizeof(char *)))
252                     printf("%s", lowtag_Names[idx]);
253             else
254                     printf("unknown type (0x%0x)", type);
255             break;
256     }
257 }
258
259 static void print_otherimm(lispobj obj)
260 {
261     int type, idx;
262
263     type = widetag_of(obj);
264     idx = type >> 2;
265
266     if (idx < (sizeof(lowtag_Names) / sizeof(char *)))
267             printf(", %s", lowtag_Names[idx]);
268     else
269             printf(", unknown type (0x%0x)", type);
270
271     switch (widetag_of(obj)) {
272         case BASE_CHAR_WIDETAG:
273             printf(": ");
274             brief_otherimm(obj);
275             break;
276
277         case SAP_WIDETAG:
278         case UNBOUND_MARKER_WIDETAG:
279             break;
280
281         default:
282             printf(": data=%ld", (long) (obj>>8)&0xffffff);
283             break;
284     }
285 }
286
287 static void brief_list(lispobj obj)
288 {
289     int space = 0;
290     int length = 0;
291
292     if (!is_valid_lisp_addr((os_vm_address_t)obj))
293         printf("(invalid Lisp-level address)");
294     else if (obj == NIL)
295         printf("NIL");
296     else {
297         putchar('(');
298         while (lowtag_of(obj) == LIST_POINTER_LOWTAG) {
299             struct cons *cons = (struct cons *)native_pointer(obj);
300
301             if (space)
302                 putchar(' ');
303             if (++length >= max_length) {
304                 printf("...");
305                 obj = NIL;
306                 break;
307             }
308             print_obj(NULL, cons->car);
309             obj = cons->cdr;
310             space = 1;
311             if (obj == NIL)
312                 break;
313         }
314         if (obj != NIL) {
315             printf(" . ");
316             print_obj(NULL, obj);
317         }
318         putchar(')');
319     }
320 }
321
322 static void print_list(lispobj obj)
323 {
324     if (!is_valid_lisp_addr((os_vm_address_t)obj)) {
325         printf("(invalid address)");
326     } else if (obj == NIL) {
327         printf(" (NIL)");
328     } else {
329         struct cons *cons = (struct cons *)native_pointer(obj);
330
331         print_obj("car: ", cons->car);
332         print_obj("cdr: ", cons->cdr);
333     }
334 }
335
336 static void brief_struct(lispobj obj)
337 {
338     printf("#<ptr to 0x%08lx instance>",
339            (unsigned long) ((struct instance *)native_pointer(obj))->slots[0]);
340 }
341
342 static void print_struct(lispobj obj)
343 {
344     struct instance *instance = (struct instance *)native_pointer(obj);
345     int i;
346     char buffer[16];
347     print_obj("type: ", ((struct instance *)native_pointer(obj))->slots[0]);
348     for (i = 1; i < HeaderValue(instance->header); i++) {
349         sprintf(buffer, "slot %d: ", i);
350         print_obj(buffer, instance->slots[i]);
351     }
352 }
353
354 static void brief_otherptr(lispobj obj)
355 {
356     lispobj *ptr, header;
357     int type;
358     struct symbol *symbol;
359     struct vector *vector;
360     char *charptr;
361
362     ptr = (lispobj *) native_pointer(obj);
363
364     if (!is_valid_lisp_addr((os_vm_address_t)obj)) {
365             printf("(invalid address)");
366             return;
367     }
368
369     header = *ptr;
370     type = widetag_of(header);
371     switch (type) {
372         case SYMBOL_HEADER_WIDETAG:
373             symbol = (struct symbol *)ptr;
374             vector = (struct vector *)native_pointer(symbol->name);
375             for (charptr = (char *)vector->data; *charptr != '\0'; charptr++) {
376                 if (*charptr == '"')
377                     putchar('\\');
378                 putchar(*charptr);
379             }
380             break;
381
382         case SIMPLE_STRING_WIDETAG:
383             vector = (struct vector *)ptr;
384             putchar('"');
385             for (charptr = (char *)vector->data; *charptr != '\0'; charptr++) {
386                 if (*charptr == '"')
387                     putchar('\\');
388                 putchar(*charptr);
389             }
390             putchar('"');
391             break;
392
393         default:
394             printf("#<ptr to ");
395             brief_otherimm(header);
396             putchar('>');
397     }
398 }
399
400 static void print_slots(char **slots, int count, lispobj *ptr)
401 {
402     while (count-- > 0) {
403         if (*slots) {
404             print_obj(*slots++, *ptr++);
405         } else {
406             print_obj("???: ", *ptr++);
407         }
408     }
409 }
410
411 /* FIXME: Yikes again! This, like subtype_Names[], needs to depend
412  * on the values in sbcl.h (or perhaps be generated automatically
413  * by GENESIS as part of sbcl.h). */
414 static char *symbol_slots[] = {"value: ", "unused: ",
415     "plist: ", "name: ", "package: ", NULL};
416 static char *ratio_slots[] = {"numer: ", "denom: ", NULL};
417 static char *complex_slots[] = {"real: ", "imag: ", NULL};
418 static char *code_slots[] = {"words: ", "entry: ", "debug: ", NULL};
419 static char *fn_slots[] = {"self: ", "next: ", "name: ", "arglist: ", "type: ", NULL};
420 static char *closure_slots[] = {"fn: ", NULL};
421 static char *funcallable_instance_slots[] = {"fn: ", "lexenv: ", "layout: ", NULL};
422 static char *weak_pointer_slots[] = {"value: ", NULL};
423 static char *fdefn_slots[] = {"name: ", "function: ", "raw_addr: ", NULL};
424 static char *value_cell_slots[] = {"value: ", NULL};
425
426 static void print_otherptr(lispobj obj)
427 {
428     if (!is_valid_lisp_addr((os_vm_address_t)obj)) {
429         printf("(invalid address)");
430     } else {
431 #ifndef alpha
432         lispobj *ptr;
433         unsigned long header;
434         unsigned long length;
435 #else
436         u32 *ptr;
437         u32 header;
438         u32 length;
439 #endif
440         int count, type, index;
441         char *cptr, buffer[16];
442
443         ptr = (lispobj*) native_pointer(obj);
444         if (ptr == NULL) {
445                 printf(" (NULL Pointer)");
446                 return;
447         }
448
449         header = *ptr++;
450         length = (*ptr) >> 2;
451         count = header>>8;
452         type = widetag_of(header);
453
454         print_obj("header: ", header);
455         if (lowtag_of(header) != OTHER_IMMEDIATE_0_LOWTAG &&
456             lowtag_of(header) != OTHER_IMMEDIATE_1_LOWTAG) {
457             NEWLINE_OR_RETURN;
458             printf("(invalid header object)");
459             return;
460         }
461
462         switch (type) {
463             case BIGNUM_WIDETAG:
464                 ptr += count;
465                 NEWLINE_OR_RETURN;
466                 printf("0x");
467                 while (count-- > 0)
468                     printf("%08lx", (unsigned long) *--ptr);
469                 break;
470
471             case RATIO_WIDETAG:
472                 print_slots(ratio_slots, count, ptr);
473                 break;
474
475             case COMPLEX_WIDETAG:
476                 print_slots(complex_slots, count, ptr);
477                 break;
478
479             case SYMBOL_HEADER_WIDETAG:
480                 print_slots(symbol_slots, count, ptr);
481                 break;
482
483             case SINGLE_FLOAT_WIDETAG:
484                 NEWLINE_OR_RETURN;
485                 printf("%g", ((struct single_float *)native_pointer(obj))->value);
486                 break;
487
488             case DOUBLE_FLOAT_WIDETAG:
489                 NEWLINE_OR_RETURN;
490                 printf("%g", ((struct double_float *)native_pointer(obj))->value);
491                 break;
492
493 #ifdef LONG_FLOAT_WIDETAG
494             case LONG_FLOAT_WIDETAG:
495                 NEWLINE_OR_RETURN;
496                 printf("%Lg", ((struct long_float *)native_pointer(obj))->value);
497                 break;
498 #endif
499
500 #ifdef COMPLEX_SINGLE_FLOAT_WIDETAG
501             case COMPLEX_SINGLE_FLOAT_WIDETAG:
502                 NEWLINE_OR_RETURN;
503                 printf("%g", ((struct complex_single_float *)native_pointer(obj))->real);
504                 NEWLINE_OR_RETURN;
505                 printf("%g", ((struct complex_single_float *)native_pointer(obj))->imag);
506                 break;
507 #endif
508
509 #ifdef COMPLEX_DOUBLE_FLOAT_WIDETAG
510             case COMPLEX_DOUBLE_FLOAT_WIDETAG:
511                 NEWLINE_OR_RETURN;
512                 printf("%g", ((struct complex_double_float *)native_pointer(obj))->real);
513                 NEWLINE_OR_RETURN;
514                 printf("%g", ((struct complex_double_float *)native_pointer(obj))->imag);
515                 break;
516 #endif
517
518 #ifdef COMPLEX_LONG_FLOAT_WIDETAG
519             case COMPLEX_LONG_FLOAT_WIDETAG:
520                 NEWLINE_OR_RETURN;
521                 printf("%Lg", ((struct complex_long_float *)native_pointer(obj))->real);
522                 NEWLINE_OR_RETURN;
523                 printf("%Lg", ((struct complex_long_float *)native_pointer(obj))->imag);
524                 break;
525 #endif
526
527             case SIMPLE_STRING_WIDETAG:
528                 NEWLINE_OR_RETURN;
529                 cptr = (char *)(ptr+1);
530                 putchar('"');
531                 while (length-- > 0)
532                     putchar(*cptr++);
533                 putchar('"');
534                 break;
535
536             case SIMPLE_VECTOR_WIDETAG:
537                 NEWLINE_OR_RETURN;
538                 printf("length = %ld", length);
539                 ptr++;
540                 index = 0;
541                 while (length-- > 0) {
542                     sprintf(buffer, "%d: ", index++);
543                     print_obj(buffer, *ptr++);
544                 }
545                 break;
546
547             case INSTANCE_HEADER_WIDETAG:
548                 NEWLINE_OR_RETURN;
549                 printf("length = %ld", (long) count);
550                 index = 0;
551                 while (count-- > 0) {
552                     sprintf(buffer, "%d: ", index++);
553                     print_obj(buffer, *ptr++);
554                 }
555                 break;
556
557             case SIMPLE_ARRAY_WIDETAG:
558             case SIMPLE_BIT_VECTOR_WIDETAG:
559             case SIMPLE_ARRAY_UNSIGNED_BYTE_2_WIDETAG:
560             case SIMPLE_ARRAY_UNSIGNED_BYTE_4_WIDETAG:
561             case SIMPLE_ARRAY_UNSIGNED_BYTE_8_WIDETAG:
562             case SIMPLE_ARRAY_UNSIGNED_BYTE_16_WIDETAG:
563             case SIMPLE_ARRAY_UNSIGNED_BYTE_32_WIDETAG:
564 #ifdef SIMPLE_ARRAY_SIGNED_BYTE_8_WIDETAG
565             case SIMPLE_ARRAY_SIGNED_BYTE_8_WIDETAG:
566 #endif
567 #ifdef SIMPLE_ARRAY_SIGNED_BYTE_16_WIDETAG
568             case SIMPLE_ARRAY_SIGNED_BYTE_16_WIDETAG:
569 #endif
570 #ifdef SIMPLE_ARRAY_SIGNED_BYTE_30_WIDETAG
571             case SIMPLE_ARRAY_SIGNED_BYTE_30_WIDETAG:
572 #endif
573 #ifdef SIMPLE_ARRAY_SIGNED_BYTE_32_WIDETAG
574             case SIMPLE_ARRAY_SIGNED_BYTE_32_WIDETAG:
575 #endif
576             case SIMPLE_ARRAY_SINGLE_FLOAT_WIDETAG:
577             case SIMPLE_ARRAY_DOUBLE_FLOAT_WIDETAG:
578 #ifdef SIMPLE_ARRAY_LONG_FLOAT_WIDETAG
579             case SIMPLE_ARRAY_LONG_FLOAT_WIDETAG:
580 #endif
581 #ifdef SIMPLE_ARRAY_COMPLEX_SINGLE_FLOAT_WIDETAG
582             case SIMPLE_ARRAY_COMPLEX_SINGLE_FLOAT_WIDETAG:
583 #endif
584 #ifdef SIMPLE_ARRAY_COMPLEX_DOUBLE_FLOAT_WIDETAG
585             case SIMPLE_ARRAY_COMPLEX_DOUBLE_FLOAT_WIDETAG:
586 #endif
587 #ifdef SIMPLE_ARRAY_COMPLEX_LONG_FLOAT_WIDETAG
588             case SIMPLE_ARRAY_COMPLEX_LONG_FLOAT_WIDETAG:
589 #endif
590             case COMPLEX_STRING_WIDETAG:
591             case COMPLEX_BIT_VECTOR_WIDETAG:
592             case COMPLEX_VECTOR_WIDETAG:
593             case COMPLEX_ARRAY_WIDETAG:
594                 break;
595
596             case CODE_HEADER_WIDETAG:
597                 print_slots(code_slots, count-1, ptr);
598                 break;
599
600             case SIMPLE_FUN_HEADER_WIDETAG:
601             case CLOSURE_FUN_HEADER_WIDETAG:
602                 print_slots(fn_slots, 5, ptr);
603                 break;
604
605             case RETURN_PC_HEADER_WIDETAG:
606                 print_obj("code: ", obj - (count * 4));
607                 break;
608
609             case CLOSURE_HEADER_WIDETAG:
610                 print_slots(closure_slots, count, ptr);
611                 break;
612
613             case FUNCALLABLE_INSTANCE_HEADER_WIDETAG:
614                 print_slots(funcallable_instance_slots, count, ptr);
615                 break;
616
617             case VALUE_CELL_HEADER_WIDETAG:
618                 print_slots(value_cell_slots, 1, ptr);
619                 break;
620
621             case SAP_WIDETAG:
622                 NEWLINE_OR_RETURN;
623 #ifndef alpha
624                 printf("0x%08lx", (unsigned long) *ptr);
625 #else
626                 printf("0x%016lx", *(lispobj*)(ptr+1));
627 #endif
628                 break;
629
630             case WEAK_POINTER_WIDETAG:
631                 print_slots(weak_pointer_slots, 1, ptr);
632                 break;
633
634             case BASE_CHAR_WIDETAG:
635             case UNBOUND_MARKER_WIDETAG:
636                 NEWLINE_OR_RETURN;
637                 printf("pointer to an immediate?");
638                 break;
639
640             case FDEFN_WIDETAG:
641                 print_slots(fdefn_slots, count, ptr);
642                 break;
643                 
644             default:
645                 NEWLINE_OR_RETURN;
646                 printf("Unknown header object?");
647                 break;
648         }
649     }
650 }
651
652 static void print_obj(char *prefix, lispobj obj)
653 {
654     static void (*verbose_fns[])(lispobj obj)
655         = {print_fixnum, print_otherptr, print_otherimm, print_list,
656            print_fixnum, print_struct, print_otherimm, print_otherptr};
657     static void (*brief_fns[])(lispobj obj)
658         = {brief_fixnum, brief_otherptr, brief_otherimm, brief_list,
659            brief_fixnum, brief_struct, brief_otherimm, brief_otherptr};
660     int type = lowtag_of(obj);
661     struct var *var = lookup_by_obj(obj);
662     char buffer[256];
663     boolean verbose = cur_depth < brief_depth;
664
665     if (!continue_p(verbose))
666         return;
667
668     if (var != NULL && var_clock(var) == cur_clock)
669         dont_descend = 1;
670
671     if (var == NULL &&
672         /* FIXME: What does this "x & y & z & .." expression mean? */
673         (obj & FUN_POINTER_LOWTAG & LIST_POINTER_LOWTAG & INSTANCE_POINTER_LOWTAG & OTHER_POINTER_LOWTAG) != 0)
674         var = define_var(NULL, obj, 0);
675
676     if (var != NULL)
677         var_setclock(var, cur_clock);
678
679     cur_depth++;
680     if (verbose) {
681         if (var != NULL) {
682             sprintf(buffer, "$%s=", var_name(var));
683             newline(buffer);
684         }
685         else
686             newline(NULL);
687         printf("%s0x%08lx: ", prefix, (unsigned long) obj);
688         if (cur_depth < brief_depth) {
689             fputs(lowtag_Names[type], stdout);
690             (*verbose_fns[type])(obj);
691         }
692         else
693             (*brief_fns[type])(obj);
694     }
695     else {
696         if (dont_descend)
697             printf("$%s", var_name(var));
698         else {
699             if (var != NULL)
700                 printf("$%s=", var_name(var));
701             (*brief_fns[type])(obj);
702         }
703     }
704     cur_depth--;
705     dont_descend = 0;
706 }
707
708 void reset_printer()
709 {
710     cur_clock++;
711     cur_lines = 0;
712     dont_descend = 0;
713 }
714
715 void print(lispobj obj)
716 {
717     skip_newline = 1;
718     cur_depth = 0;
719     max_depth = 5;
720     max_lines = 20;
721
722     print_obj("", obj);
723
724     putchar('\n');
725 }
726
727 void brief_print(lispobj obj)
728 {
729     skip_newline = 1;
730     cur_depth = 0;
731     max_depth = 1;
732     max_lines = 5000;
733
734     print_obj("", obj);
735     putchar('\n');
736 }
737
738 #else
739
740 void
741 brief_print(lispobj obj)
742 {
743     printf("lispobj 0x%lx\n", (unsigned long)obj);
744 }
745      
746 #endif /* defined(LISP_FEATURE_SB_LDB) */