2cc6f1bfcda10dd4c7e4aec6142003b4503a38e8
[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 "monitor.h"
31 #include "vars.h"
32 #include "os.h"
33
34 static int max_lines = 20, cur_lines = 0;
35 static int max_depth = 5, brief_depth = 2, cur_depth = 0;
36 static int max_length = 5;
37 static boolean dont_descend = 0, skip_newline = 0;
38 static int cur_clock = 0;
39
40 static void print_obj(char *prefix, lispobj obj);
41
42 #define NEWLINE_OR_RETURN if (continue_p(1)) newline(NULL); else return;
43
44 char *lowtag_Names[] = {
45     "even fixnum",
46     "instance pointer",
47     "other immediate [0]",
48     "list pointer",
49     "odd fixnum",
50     "function pointer",
51     "other immediate [1]",
52     "other pointer"
53 };
54
55 /* FIXME: Yikes! This table implicitly depends on the values in sbcl.h,
56  * but doesn't actually depend on them, so if they change, it gets
57  * all broken. We should either get rid of it or
58  * rewrite the code so that it's cleanly initialized by gc_init_tables[]
59  * in a way which varies correctly with the values in sbcl.h. */
60 char *subtype_Names[] = {
61     "unused 0",
62     "unused 1",
63     "bignum",
64     "ratio",
65     "single float",
66     "double float",
67 #ifdef LONG_FLOAT_WIDETAG
68     "long float",
69 #endif
70     "complex",
71 #ifdef COMPLEX_SINGLE_FLOAT_WIDETAG
72     "complex single float",
73 #endif
74 #ifdef COMPLEX_DOUBLE_FLOAT_WIDETAG
75     "complex double float",
76 #endif
77 #ifdef COMPLEX_LONG_FLOAT_WIDETAG
78     "complex long float",
79 #endif
80     "simple-array",
81     "simple-string",
82     "simple-bit-vector",
83     "simple-vector",
84     "(simple-array (unsigned-byte 2) (*))",
85     "(simple-array (unsigned-byte 4) (*))",
86     "(simple-array (unsigned-byte 8) (*))",
87     "(simple-array (unsigned-byte 16) (*))",
88     "(simple-array (unsigned-byte 32) (*))",
89 #ifdef SIMPLE_ARRAY_SIGNED_BYTE_8_WIDETAG
90     "(simple-array (signed-byte 8) (*))",
91 #endif
92 #ifdef SIMPLE_ARRAY_SIGNED_BYTE_16_WIDETAG
93     "(simple-array (signed-byte 16) (*))",
94 #endif
95 #ifdef SIMPLE_ARRAY_SIGNED_BYTE_30_WIDETAG
96     "(simple-array fixnum (*))",
97 #endif
98 #ifdef SIMPLE_ARRAY_SIGNED_BYTE_32_WIDETAG
99     "(simple-array (signed-byte 32) (*))",
100 #endif
101     "(simple-array single-float (*))",
102     "(simple-array double-float (*))",
103 #ifdef SIMPLE_ARRAY_LONG_FLOAT_WIDETAG
104     "(simple-array long-float (*))",
105 #endif
106 #ifdef SIMPLE_ARRAY_COMPLEX_SINGLE_FLOAT_WIDETAG
107     "(simple-array (complex single-float) (*))",
108 #endif
109 #ifdef SIMPLE_ARRAY_COMPLEX_DOUBLE_FLOAT_WIDETAG
110     "(simple-array (complex double-float) (*))",
111 #endif
112 #ifdef SIMPLE_ARRAY_COMPLEX_LONG_FLOAT_WIDETAG
113     "(simple-array (complex long-float) (*))",
114 #endif
115     "complex-string",
116     "complex-bit-vector",
117     "(array * (*))",
118     "array",
119     "code header",
120     "function header",
121     "closure header",
122     "funcallable-instance header",
123     "unused function header 1",
124     "unused function header 2",
125     "unused function header 3",
126     "closure function header",
127     "return PC header",
128     "value cell header",
129     "symbol header",
130     "character",
131     "SAP",
132     "unbound marker",
133     "weak pointer",
134     "instance header",
135     "fdefn"
136 };
137
138 static void indent(int in)
139 {
140     static char *spaces = "                                                                ";
141
142     while (in > 64) {
143         fputs(spaces, stdout);
144         in -= 64;
145     }
146     if (in != 0)
147         fputs(spaces + 64 - in, stdout);
148 }
149
150 static boolean continue_p(boolean newline)
151 {
152     char buffer[256];
153
154     if (cur_depth >= max_depth || dont_descend)
155         return 0;
156
157     if (newline) {
158         if (skip_newline)
159             skip_newline = 0;
160         else
161             putchar('\n');
162
163         if (cur_lines >= max_lines) {
164             printf("More? [y] ");
165             fflush(stdout);
166
167             fgets(buffer, sizeof(buffer), stdin);
168
169             if (buffer[0] == 'n' || buffer[0] == 'N')
170                 throw_to_monitor();
171             else
172                 cur_lines = 0;
173         }
174     }
175
176     return 1;
177 }
178
179 static void newline(char *label)
180 {
181     cur_lines++;
182     if (label != NULL)
183         fputs(label, stdout);
184     putchar('\t');
185     indent(cur_depth * 2);
186 }
187
188
189 static void brief_fixnum(lispobj obj)
190 {
191 #ifndef alpha
192     printf("%ld", ((long)obj)>>2);
193 #else
194     printf("%d", ((s32)obj)>>2);
195 #endif
196 }
197
198 static void print_fixnum(lispobj obj)
199 {
200 #ifndef alpha
201     printf(": %ld", ((long)obj)>>2);
202 #else
203     printf(": %d", ((s32)obj)>>2);
204 #endif
205 }
206
207 static void brief_otherimm(lispobj obj)
208 {
209     int type, c, idx;
210     char buffer[10];
211
212     type = widetag_of(obj);
213     switch (type) {
214         case BASE_CHAR_WIDETAG:
215             c = (obj>>8)&0xff;
216             switch (c) {
217                 case '\0':
218                     printf("#\\Null");
219                     break;
220                 case '\n':
221                     printf("#\\Newline");
222                     break;
223                 case '\b':
224                     printf("#\\Backspace");
225                     break;
226                 case '\177':
227                     printf("#\\Delete");
228                     break;
229                 default:
230                     strcpy(buffer, "#\\");
231                     if (c >= 128) {
232                         strcat(buffer, "m-");
233                         c -= 128;
234                     }
235                     if (c < 32) {
236                         strcat(buffer, "c-");
237                         c += '@';
238                     }
239                     printf("%s%c", buffer, c);
240                     break;
241             }
242             break;
243
244         case UNBOUND_MARKER_WIDETAG:
245             printf("<unbound marker>");
246             break;
247
248         default:
249             idx = type >> 2;
250             if (idx < (sizeof(lowtag_Names) / sizeof(char *)))
251                     printf("%s", lowtag_Names[idx]);
252             else
253                     printf("unknown type (0x%0x)", type);
254             break;
255     }
256 }
257
258 static void print_otherimm(lispobj obj)
259 {
260     int type, idx;
261
262     type = widetag_of(obj);
263     idx = type >> 2;
264
265     if (idx < (sizeof(lowtag_Names) / sizeof(char *)))
266             printf(", %s", lowtag_Names[idx]);
267     else
268             printf(", unknown type (0x%0x)", type);
269
270     switch (widetag_of(obj)) {
271         case BASE_CHAR_WIDETAG:
272             printf(": ");
273             brief_otherimm(obj);
274             break;
275
276         case SAP_WIDETAG:
277         case UNBOUND_MARKER_WIDETAG:
278             break;
279
280         default:
281             printf(": data=%ld", (long) (obj>>8)&0xffffff);
282             break;
283     }
284 }
285
286 static void brief_list(lispobj obj)
287 {
288     int space = 0;
289     int length = 0;
290
291     if (!is_valid_lisp_addr((os_vm_address_t)obj))
292         printf("(invalid Lisp-level address)");
293     else if (obj == NIL)
294         printf("NIL");
295     else {
296         putchar('(');
297         while (lowtag_of(obj) == LIST_POINTER_LOWTAG) {
298             struct cons *cons = (struct cons *)native_pointer(obj);
299
300             if (space)
301                 putchar(' ');
302             if (++length >= max_length) {
303                 printf("...");
304                 obj = NIL;
305                 break;
306             }
307             print_obj(NULL, cons->car);
308             obj = cons->cdr;
309             space = 1;
310             if (obj == NIL)
311                 break;
312         }
313         if (obj != NIL) {
314             printf(" . ");
315             print_obj(NULL, obj);
316         }
317         putchar(')');
318     }
319 }
320
321 static void print_list(lispobj obj)
322 {
323     if (!is_valid_lisp_addr((os_vm_address_t)obj)) {
324         printf("(invalid address)");
325     } else if (obj == NIL) {
326         printf(" (NIL)");
327     } else {
328         struct cons *cons = (struct cons *)native_pointer(obj);
329
330         print_obj("car: ", cons->car);
331         print_obj("cdr: ", cons->cdr);
332     }
333 }
334
335 static void brief_struct(lispobj obj)
336 {
337     printf("#<ptr to 0x%08lx instance>",
338            (unsigned long) ((struct instance *)native_pointer(obj))->slots[0]);
339 }
340
341 static void print_struct(lispobj obj)
342 {
343     struct instance *instance = (struct instance *)native_pointer(obj);
344     int i;
345     char buffer[16];
346     print_obj("type: ", ((struct instance *)native_pointer(obj))->slots[0]);
347     for (i = 1; i < HeaderValue(instance->header); i++) {
348         sprintf(buffer, "slot %d: ", i);
349         print_obj(buffer, instance->slots[i]);
350     }
351 }
352
353 static void brief_otherptr(lispobj obj)
354 {
355     lispobj *ptr, header;
356     int type;
357     struct symbol *symbol;
358     struct vector *vector;
359     char *charptr;
360
361     ptr = (lispobj *) native_pointer(obj);
362
363     if (!is_valid_lisp_addr((os_vm_address_t)obj)) {
364             printf("(invalid address)");
365             return;
366     }
367
368     header = *ptr;
369     type = widetag_of(header);
370     switch (type) {
371         case SYMBOL_HEADER_WIDETAG:
372             symbol = (struct symbol *)ptr;
373             vector = (struct vector *)native_pointer(symbol->name);
374             for (charptr = (char *)vector->data; *charptr != '\0'; charptr++) {
375                 if (*charptr == '"')
376                     putchar('\\');
377                 putchar(*charptr);
378             }
379             break;
380
381         case SIMPLE_STRING_WIDETAG:
382             vector = (struct vector *)ptr;
383             putchar('"');
384             for (charptr = (char *)vector->data; *charptr != '\0'; charptr++) {
385                 if (*charptr == '"')
386                     putchar('\\');
387                 putchar(*charptr);
388             }
389             putchar('"');
390             break;
391
392         default:
393             printf("#<ptr to ");
394             brief_otherimm(header);
395             putchar('>');
396     }
397 }
398
399 static void print_slots(char **slots, int count, lispobj *ptr)
400 {
401     while (count-- > 0) {
402         if (*slots) {
403             print_obj(*slots++, *ptr++);
404         } else {
405             print_obj("???: ", *ptr++);
406         }
407     }
408 }
409
410 /* FIXME: Yikes again! This, like subtype_Names[], needs to depend
411  * on the values in sbcl.h (or perhaps be generated automatically
412  * by GENESIS as part of sbcl.h). */
413 static char *symbol_slots[] = {"value: ", "unused: ",
414     "plist: ", "name: ", "package: ", NULL};
415 static char *ratio_slots[] = {"numer: ", "denom: ", NULL};
416 static char *complex_slots[] = {"real: ", "imag: ", NULL};
417 static char *code_slots[] = {"words: ", "entry: ", "debug: ", NULL};
418 static char *fn_slots[] = {
419     "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_struct, print_otherimm, print_list,
656            print_fixnum, print_otherptr, print_otherimm, print_otherptr};
657     static void (*brief_fns[])(lispobj obj)
658         = {brief_fixnum, brief_struct, brief_otherimm, brief_list,
659            brief_fixnum, brief_otherptr, 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) */