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