d39586d27ea96259d6150cf34f2e25d152cd5de2
[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
26 /* This file can be skipped if we're not supporting LDB. */
27 #if defined(LISP_FEATURE_SB_LDB)
28
29 #include "sbcl.h"
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     "function pointer",
47     "other immediate [0]",
48     "list pointer",
49     "odd fixnum",
50     "instance 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(SUBNAMES_WIDETAG) / sizeof(char *)))
251                     printf("%s", SUBNAMES_WIDETAG[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(SUBNAMES_WIDETAG) / sizeof(char *)))
266             printf(", %s", SUBNAMES_WIDETAG[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 SUBNAMES_WIDETAG[], needs to depend
411  * on the values in sbcl.h. */
412 static char *symbol_slots[] = {"value: ", "unused: ",
413     "plist: ", "name: ", "package: ", NULL};
414 static char *ratio_slots[] = {"numer: ", "denom: ", NULL};
415 static char *complex_slots[] = {"real: ", "imag: ", NULL};
416 static char *code_slots[] = {"words: ", "entry: ", "debug: ", NULL};
417 static char *fn_slots[] = {"self: ", "next: ", "name: ", "arglist: ", "type: ", NULL};
418 static char *closure_slots[] = {"fn: ", NULL};
419 static char *funcallable_instance_slots[] = {"fn: ", "lexenv: ", "layout: ", NULL};
420 static char *weak_pointer_slots[] = {"value: ", NULL};
421 static char *fdefn_slots[] = {"name: ", "function: ", "raw_addr: ", NULL};
422 static char *value_cell_slots[] = {"value: ", NULL};
423
424 static void print_otherptr(lispobj obj)
425 {
426     if (!is_valid_lisp_addr((os_vm_address_t)obj)) {
427         printf("(invalid address)");
428     } else {
429 #ifndef alpha
430         lispobj *ptr;
431         unsigned long header;
432         unsigned long length;
433 #else
434         u32 *ptr;
435         u32 header;
436         u32 length;
437 #endif
438         int count, type, index;
439         char *cptr, buffer[16];
440
441         ptr = (lispobj*) native_pointer(obj);
442         if (ptr == NULL) {
443                 printf(" (NULL Pointer)");
444                 return;
445         }
446
447         header = *ptr++;
448         length = (*ptr) >> 2;
449         count = header>>8;
450         type = widetag_of(header);
451
452         print_obj("header: ", header);
453         if (lowtag_of(header) != OTHER_IMMEDIATE_0_LOWTAG &&
454             lowtag_of(header) != OTHER_IMMEDIATE_1_LOWTAG) {
455             NEWLINE_OR_RETURN;
456             printf("(invalid header object)");
457             return;
458         }
459
460         switch (type) {
461             case BIGNUM_WIDETAG:
462                 ptr += count;
463                 NEWLINE_OR_RETURN;
464                 printf("0x");
465                 while (count-- > 0)
466                     printf("%08lx", (unsigned long) *--ptr);
467                 break;
468
469             case RATIO_WIDETAG:
470                 print_slots(ratio_slots, count, ptr);
471                 break;
472
473             case COMPLEX_WIDETAG:
474                 print_slots(complex_slots, count, ptr);
475                 break;
476
477             case SYMBOL_HEADER_WIDETAG:
478                 print_slots(symbol_slots, count, ptr);
479                 break;
480
481             case SINGLE_FLOAT_WIDETAG:
482                 NEWLINE_OR_RETURN;
483                 printf("%g", ((struct single_float *)native_pointer(obj))->value);
484                 break;
485
486             case DOUBLE_FLOAT_WIDETAG:
487                 NEWLINE_OR_RETURN;
488                 printf("%g", ((struct double_float *)native_pointer(obj))->value);
489                 break;
490
491 #ifdef LONG_FLOAT_WIDETAG
492             case LONG_FLOAT_WIDETAG:
493                 NEWLINE_OR_RETURN;
494                 printf("%Lg", ((struct long_float *)native_pointer(obj))->value);
495                 break;
496 #endif
497
498 #ifdef COMPLEX_SINGLE_FLOAT_WIDETAG
499             case COMPLEX_SINGLE_FLOAT_WIDETAG:
500                 NEWLINE_OR_RETURN;
501                 printf("%g", ((struct complex_single_float *)native_pointer(obj))->real);
502                 NEWLINE_OR_RETURN;
503                 printf("%g", ((struct complex_single_float *)native_pointer(obj))->imag);
504                 break;
505 #endif
506
507 #ifdef COMPLEX_DOUBLE_FLOAT_WIDETAG
508             case COMPLEX_DOUBLE_FLOAT_WIDETAG:
509                 NEWLINE_OR_RETURN;
510                 printf("%g", ((struct complex_double_float *)native_pointer(obj))->real);
511                 NEWLINE_OR_RETURN;
512                 printf("%g", ((struct complex_double_float *)native_pointer(obj))->imag);
513                 break;
514 #endif
515
516 #ifdef COMPLEX_LONG_FLOAT_WIDETAG
517             case COMPLEX_LONG_FLOAT_WIDETAG:
518                 NEWLINE_OR_RETURN;
519                 printf("%Lg", ((struct complex_long_float *)native_pointer(obj))->real);
520                 NEWLINE_OR_RETURN;
521                 printf("%Lg", ((struct complex_long_float *)native_pointer(obj))->imag);
522                 break;
523 #endif
524
525             case SIMPLE_STRING_WIDETAG:
526                 NEWLINE_OR_RETURN;
527                 cptr = (char *)(ptr+1);
528                 putchar('"');
529                 while (length-- > 0)
530                     putchar(*cptr++);
531                 putchar('"');
532                 break;
533
534             case SIMPLE_VECTOR_WIDETAG:
535                 NEWLINE_OR_RETURN;
536                 printf("length = %ld", length);
537                 ptr++;
538                 index = 0;
539                 while (length-- > 0) {
540                     sprintf(buffer, "%d: ", index++);
541                     print_obj(buffer, *ptr++);
542                 }
543                 break;
544
545             case INSTANCE_HEADER_WIDETAG:
546                 NEWLINE_OR_RETURN;
547                 printf("length = %ld", (long) count);
548                 index = 0;
549                 while (count-- > 0) {
550                     sprintf(buffer, "%d: ", index++);
551                     print_obj(buffer, *ptr++);
552                 }
553                 break;
554
555             case SIMPLE_ARRAY_WIDETAG:
556             case SIMPLE_BIT_VECTOR_WIDETAG:
557             case SIMPLE_ARRAY_UNSIGNED_BYTE_2_WIDETAG:
558             case SIMPLE_ARRAY_UNSIGNED_BYTE_4_WIDETAG:
559             case SIMPLE_ARRAY_UNSIGNED_BYTE_8_WIDETAG:
560             case SIMPLE_ARRAY_UNSIGNED_BYTE_16_WIDETAG:
561             case SIMPLE_ARRAY_UNSIGNED_BYTE_32_WIDETAG:
562 #ifdef SIMPLE_ARRAY_SIGNED_BYTE_8_WIDETAG
563             case SIMPLE_ARRAY_SIGNED_BYTE_8_WIDETAG:
564 #endif
565 #ifdef SIMPLE_ARRAY_SIGNED_BYTE_16_WIDETAG
566             case SIMPLE_ARRAY_SIGNED_BYTE_16_WIDETAG:
567 #endif
568 #ifdef SIMPLE_ARRAY_SIGNED_BYTE_30_WIDETAG
569             case SIMPLE_ARRAY_SIGNED_BYTE_30_WIDETAG:
570 #endif
571 #ifdef SIMPLE_ARRAY_SIGNED_BYTE_32_WIDETAG
572             case SIMPLE_ARRAY_SIGNED_BYTE_32_WIDETAG:
573 #endif
574             case SIMPLE_ARRAY_SINGLE_FLOAT_WIDETAG:
575             case SIMPLE_ARRAY_DOUBLE_FLOAT_WIDETAG:
576 #ifdef SIMPLE_ARRAY_LONG_FLOAT_WIDETAG
577             case SIMPLE_ARRAY_LONG_FLOAT_WIDETAG:
578 #endif
579 #ifdef SIMPLE_ARRAY_COMPLEX_SINGLE_FLOAT_WIDETAG
580             case SIMPLE_ARRAY_COMPLEX_SINGLE_FLOAT_WIDETAG:
581 #endif
582 #ifdef SIMPLE_ARRAY_COMPLEX_DOUBLE_FLOAT_WIDETAG
583             case SIMPLE_ARRAY_COMPLEX_DOUBLE_FLOAT_WIDETAG:
584 #endif
585 #ifdef SIMPLE_ARRAY_COMPLEX_LONG_FLOAT_WIDETAG
586             case SIMPLE_ARRAY_COMPLEX_LONG_FLOAT_WIDETAG:
587 #endif
588             case COMPLEX_STRING_WIDETAG:
589             case COMPLEX_BIT_VECTOR_WIDETAG:
590             case COMPLEX_VECTOR_WIDETAG:
591             case COMPLEX_ARRAY_WIDETAG:
592                 break;
593
594             case CODE_HEADER_WIDETAG:
595                 print_slots(code_slots, count-1, ptr);
596                 break;
597
598             case SIMPLE_FUN_HEADER_WIDETAG:
599             case CLOSURE_FUN_HEADER_WIDETAG:
600                 print_slots(fn_slots, 5, ptr);
601                 break;
602
603             case RETURN_PC_HEADER_WIDETAG:
604                 print_obj("code: ", obj - (count * 4));
605                 break;
606
607             case CLOSURE_HEADER_WIDETAG:
608                 print_slots(closure_slots, count, ptr);
609                 break;
610
611             case FUNCALLABLE_INSTANCE_HEADER_WIDETAG:
612                 print_slots(funcallable_instance_slots, count, ptr);
613                 break;
614
615             case VALUE_CELL_HEADER_WIDETAG:
616                 print_slots(value_cell_slots, 1, ptr);
617                 break;
618
619             case SAP_WIDETAG:
620                 NEWLINE_OR_RETURN;
621 #ifndef alpha
622                 printf("0x%08lx", (unsigned long) *ptr);
623 #else
624                 printf("0x%016lx", *(lispobj*)(ptr+1));
625 #endif
626                 break;
627
628             case WEAK_POINTER_WIDETAG:
629                 print_slots(weak_pointer_slots, 1, ptr);
630                 break;
631
632             case BASE_CHAR_WIDETAG:
633             case UNBOUND_MARKER_WIDETAG:
634                 NEWLINE_OR_RETURN;
635                 printf("pointer to an immediate?");
636                 break;
637
638             case FDEFN_WIDETAG:
639                 print_slots(fdefn_slots, count, ptr);
640                 break;
641                 
642             default:
643                 NEWLINE_OR_RETURN;
644                 printf("Unknown header object?");
645                 break;
646         }
647     }
648 }
649
650 static void print_obj(char *prefix, lispobj obj)
651 {
652     static void (*verbose_fns[])(lispobj obj)
653         = {print_fixnum, print_otherptr, print_otherimm, print_list,
654            print_fixnum, print_struct, print_otherimm, print_otherptr};
655     static void (*brief_fns[])(lispobj obj)
656         = {brief_fixnum, brief_otherptr, brief_otherimm, brief_list,
657            brief_fixnum, brief_struct, brief_otherimm, brief_otherptr};
658     int type = lowtag_of(obj);
659     struct var *var = lookup_by_obj(obj);
660     char buffer[256];
661     boolean verbose = cur_depth < brief_depth;
662
663     if (!continue_p(verbose))
664         return;
665
666     if (var != NULL && var_clock(var) == cur_clock)
667         dont_descend = 1;
668
669     if (var == NULL &&
670         /* FIXME: What does this "x & y & z & .." expression mean? */
671         (obj & FUN_POINTER_LOWTAG & LIST_POINTER_LOWTAG & INSTANCE_POINTER_LOWTAG & OTHER_POINTER_LOWTAG) != 0)
672         var = define_var(NULL, obj, 0);
673
674     if (var != NULL)
675         var_setclock(var, cur_clock);
676
677     cur_depth++;
678     if (verbose) {
679         if (var != NULL) {
680             sprintf(buffer, "$%s=", var_name(var));
681             newline(buffer);
682         }
683         else
684             newline(NULL);
685         printf("%s0x%08lx: ", prefix, (unsigned long) obj);
686         if (cur_depth < brief_depth) {
687             fputs(lowtag_Names[type], stdout);
688             (*verbose_fns[type])(obj);
689         }
690         else
691             (*brief_fns[type])(obj);
692     }
693     else {
694         if (dont_descend)
695             printf("$%s", var_name(var));
696         else {
697             if (var != NULL)
698                 printf("$%s=", var_name(var));
699             (*brief_fns[type])(obj);
700         }
701     }
702     cur_depth--;
703     dont_descend = 0;
704 }
705
706 void reset_printer()
707 {
708     cur_clock++;
709     cur_lines = 0;
710     dont_descend = 0;
711 }
712
713 void print(lispobj obj)
714 {
715     skip_newline = 1;
716     cur_depth = 0;
717     max_depth = 5;
718     max_lines = 20;
719
720     print_obj("", obj);
721
722     putchar('\n');
723 }
724
725 void brief_print(lispobj obj)
726 {
727     skip_newline = 1;
728     cur_depth = 0;
729     max_depth = 1;
730     max_lines = 5000;
731
732     print_obj("", obj);
733     putchar('\n');
734 }
735
736 #else
737
738 void
739 brief_print(lispobj obj)
740 {
741     printf("lispobj 0x%lx\n", (unsigned long)obj);
742 }
743      
744 #endif /* defined(LISP_FEATURE_SB_LDB) */