f8a90866185dcf09df25f8d8a402ce06e321a821
[projects/cmucl/cmucl.git] / src / lisp / print.c
1 /* $Header: /Volumes/share2/src/cmucl/cvs2git/cvsroot/src/lisp/print.c,v 1.30 2010/10/22 04:07:33 rtoy Exp $ */
2
3 #include <stdio.h>
4 #include <string.h>
5 #include <stdint.h>
6 #include "print.h"
7 #include "lisp.h"
8 #include "internals.h"
9 #include "monitor.h"
10 #include "vars.h"
11 #include "os.h"
12
13 static int max_lines = 20, cur_lines = 0;
14 static int max_depth = 5, brief_depth = 2, cur_depth = 0;
15 static int max_length = 5;
16 static boolean dont_decend = FALSE, skip_newline = FALSE;
17 static int cur_clock = 0;
18
19 static void print_obj(char *prefix, lispobj obj);
20
21 #define NEWLINE if (continue_p(TRUE)) newline(NULL); else return;
22
23 char *lowtag_Names[] = {
24     "even fixnum",
25     "function pointer",
26     "other immediate [0]",
27     "list pointer",
28     "odd fixnum",
29     "instance pointer",
30     "other immediate [1]",
31     "other pointer"
32 };
33
34 char *subtype_Names[] = {
35     "unused 0",
36     "unused 1",
37     "bignum",
38     "ratio",
39     "single float",
40     "double float",
41 #ifdef type_LongFloat
42     "long float",
43 #endif
44 #ifdef type_DoubleDoubleFloat
45     "double-double float",
46 #endif    
47     "complex",
48 #ifdef type_ComplexSingleFloat
49     "complex single float",
50 #endif
51 #ifdef type_ComplexDoubleFloat
52     "complex double float",
53 #endif
54 #ifdef type_ComplexLongFloat
55     "complex long float",
56 #endif
57 #ifdef type_ComplexDoubleDoubleFloat
58     "complex double-double float",
59 #endif
60     "simple-array",
61     "simple-string",
62     "simple-bit-vector",
63     "simple-vector",
64     "(simple-array (unsigned-byte 2) (*))",
65     "(simple-array (unsigned-byte 4) (*))",
66     "(simple-array (unsigned-byte 8) (*))",
67     "(simple-array (unsigned-byte 16) (*))",
68     "(simple-array (unsigned-byte 32) (*))",
69 #ifdef type_SimpleArraySignedByte8
70     "(simple-array (signed-byte 8) (*))",
71 #endif
72 #ifdef type_SimpleArraySignedByte16
73     "(simple-array (signed-byte 16) (*))",
74 #endif
75 #ifdef type_SimpleArraySignedByte30
76     "(simple-array fixnum (*))",
77 #endif
78 #ifdef type_SimpleArraySignedByte32
79     "(simple-array (signed-byte 32) (*))",
80 #endif
81     "(simple-array single-float (*))",
82     "(simple-array double-float (*))",
83 #ifdef type_SimpleArrayLongFloat
84     "(simple-array long-float (*))",
85 #endif
86 #ifdef type_SimpleArrayDoubleDoubleFloat
87     "(simple-array double-double-float (*))",
88 #endif
89 #ifdef type_SimpleArrayComplexSingleFloat
90     "(simple-array (complex single-float) (*))",
91 #endif
92 #ifdef type_SimpleArrayComplexDoubleFloat
93     "(simple-array (complex double-float) (*))",
94 #endif
95 #ifdef type_SimpleArrayComplexLongFloat
96     "(simple-array (complex long-float) (*))",
97 #endif
98 #ifdef type_SimpleArrayComplexDoubleDoubleFloat
99     "(simple-array (complex double-double-float) (*))",
100 #endif
101     "complex-string",
102     "complex-bit-vector",
103     "(array * (*))",
104     "array",
105     "code header",
106     "function header",
107     "closure header",
108     "funcallable-instance header",
109     "byte code function",
110     "byte code closure",
111 /*    "unused function header 3",*/
112     "closure function header",
113     "return PC header",
114     "value cell header",
115     "symbol header",
116     "character",
117     "SAP",
118     "unbound marker",
119     "weak pointer",
120     "instance header",
121     "fdefn"
122 #ifdef type_ScavengerHook
123         , "scavenger hook"
124 #endif
125 };
126
127 static void
128 indent(int in)
129 {
130     static char *spaces =
131
132         "                                                                ";
133
134     while (in > 64) {
135         fputs(spaces, stdout);
136         in -= 64;
137     }
138     if (in != 0)
139         fputs(spaces + 64 - in, stdout);
140 }
141
142 static boolean
143 continue_p(boolean newline)
144 {
145     char buffer[256];
146
147     if (cur_depth >= max_depth || dont_decend)
148         return FALSE;
149
150     if (newline) {
151         if (skip_newline)
152             skip_newline = FALSE;
153         else
154             putchar('\n');
155
156         if (cur_lines >= max_lines) {
157             char *result;
158             printf("More? [y] ");
159             fflush(stdout);
160
161             result = fgets(buffer, sizeof(buffer), stdin);
162
163             if (result == NULL || buffer[0] == 'n' || buffer[0] == 'N')
164                 throw_to_monitor();
165             else
166                 cur_lines = 0;
167         }
168     }
169
170     return TRUE;
171 }
172
173 static void
174 newline(char *label)
175 {
176     cur_lines++;
177     if (label != NULL)
178         fputs(label, stdout);
179     putchar('\t');
180     indent(cur_depth * 2);
181 }
182
183
184 static void
185 brief_fixnum(lispobj obj)
186 {
187 #ifndef alpha
188     printf("%ld", ((long) obj) >> 2);
189 #else
190     printf("%d", ((s32) obj) >> 2);
191 #endif
192 }
193
194 static void
195 print_fixnum(lispobj obj)
196 {
197 #ifndef alpha
198     printf(": %ld", ((long) obj) >> 2);
199 #else
200     printf(": %d", ((s32) obj) >> 2);
201 #endif
202 }
203
204 static void
205 brief_otherimm(lispobj obj)
206 {
207     int type, c, idx;
208     char buffer[10];
209
210     type = TypeOf(obj);
211     switch (type) {
212       case type_BaseChar:
213           c = (obj >> 8) & 0xff;
214           switch (c) {
215             case '\0':
216                 printf("#\\Null");
217                 break;
218             case '\n':
219                 printf("#\\Newline");
220                 break;
221             case '\b':
222                 printf("#\\Backspace");
223                 break;
224             case '\177':
225                 printf("#\\Delete");
226                 break;
227             default:
228                 strcpy(buffer, "#\\");
229                 if (c >= 128) {
230                     strcat(buffer, "m-");
231                     c -= 128;
232                 }
233                 if (c < 32) {
234                     strcat(buffer, "c-");
235                     c += '@';
236                 }
237                 printf("%s%c", buffer, c);
238                 break;
239           }
240           break;
241
242       case type_UnboundMarker:
243           printf("<unbound marker>");
244           break;
245
246       default:
247           idx = type >> 2;
248           if (idx < (sizeof(subtype_Names) / sizeof(char *)))
249               printf("%s", subtype_Names[idx]);
250
251           else
252               printf("unknown type (0x%0x)", type);
253           break;
254     }
255 }
256
257 static void
258 print_otherimm(lispobj obj)
259 {
260     int type, idx;
261
262     type = TypeOf(obj);
263     idx = type >> 2;
264
265     if (idx < (sizeof(subtype_Names) / sizeof(char *)))
266         printf(", %s", subtype_Names[idx]);
267
268     else
269         printf(", unknown type (0x%0x)", type);
270
271     switch (TypeOf(obj)) {
272       case type_BaseChar:
273           printf(": ");
274           brief_otherimm(obj);
275           break;
276
277       case type_Sap:
278       case type_UnboundMarker:
279           break;
280
281       default:
282           printf(": data=%ld", (obj >> 8) & 0xffffff);
283           break;
284     }
285 }
286
287 static void
288 brief_list(lispobj obj)
289 {
290     int space = FALSE;
291     int length = 0;
292
293     if (!valid_addr((os_vm_address_t) obj))
294         printf("(invalid address)");
295     else if (obj == NIL)
296         printf("NIL");
297     else {
298         putchar('(');
299         while (LowtagOf(obj) == type_ListPointer) {
300             struct cons *cons = (struct cons *) PTR(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 = TRUE;
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
324 print_list(lispobj obj)
325 {
326     if (!valid_addr((os_vm_address_t) obj))
327         printf("(invalid address)");
328     else if (obj == NIL)
329         printf(" (NIL)");
330     else {
331         struct cons *cons = (struct cons *) PTR(obj);
332
333         print_obj("car: ", cons->car);
334         print_obj("cdr: ", cons->cdr);
335     }
336 }
337
338 static void
339 brief_struct(lispobj obj)
340 {
341     printf("#<ptr to 0x%08lx instance>",
342            ((struct instance *) PTR(obj))->slots[0]);
343 }
344
345 static void
346 print_struct(lispobj obj)
347 {
348     struct instance *instance = (struct instance *) PTR(obj);
349     int i;
350     char buffer[16];
351
352     print_obj("type: ", ((struct instance *) PTR(obj))->slots[0]);
353     for (i = 1; i < HeaderValue(instance->header); i++) {
354         sprintf(buffer, "slot %d: ", i);
355         print_obj(buffer, instance->slots[i]);
356     }
357 }
358
359 static void
360 print_string(struct vector* vector)
361 {
362 #ifndef UNICODE
363     char *charptr;
364     
365     for (charptr = (char *) vector->data; *charptr != '\0'; charptr++) {
366         if (*charptr == '"')
367             putchar('\\');
368         putchar(*charptr);
369     }
370 #else
371     uint16_t *charptr = (uint16_t *) vector->data;
372     int len = fixnum_value(vector->length);
373               
374     while (len-- > 0) {
375         if (*charptr == '"') {
376             putchar('\\');
377         }
378         /* Just dump out the UTF-16 data */
379         fwrite(charptr, sizeof(*charptr), 1,  stdout);
380         charptr++;
381     }
382 #endif
383 }
384
385 static void
386 brief_otherptr(lispobj obj)
387 {
388     lispobj *ptr, header;
389     int type;
390     struct symbol *symbol;
391     struct vector *vector;
392
393     ptr = (lispobj *) PTR(obj);
394
395     if (!valid_addr((os_vm_address_t) obj)) {
396         printf("(invalid address)");
397         return;
398     }
399
400     header = *ptr;
401     type = TypeOf(header);
402     switch (type) {
403       case type_SymbolHeader:
404           symbol = (struct symbol *) ptr;
405           vector = (struct vector *) PTR(symbol->name);
406           print_string(vector);
407           break;
408
409       case type_SimpleString:
410           vector = (struct vector *) ptr;
411           putchar('"');
412           print_string(vector);
413           putchar('"');
414           break;
415
416       default:
417           printf("#<ptr to ");
418           brief_otherimm(header);
419           putchar('>');
420     }
421 }
422
423 static void
424 print_slots(char **slots, int count, lispobj * ptr)
425 {
426     while (count-- > 0)
427         if (*slots)
428             print_obj(*slots++, *ptr++);
429         else
430             print_obj("???: ", *ptr++);
431 }
432
433 static char *symbol_slots[] = { "value: ", "hash: ",
434     "plist: ", "name: ", "package: ", NULL
435 };
436 static char *ratio_slots[] = { "numer: ", "denom: ", NULL };
437 static char *complex_slots[] = { "real: ", "imag: ", NULL };
438 static char *code_slots[] = { "words: ", "entry: ", "debug: ", NULL };
439 static char *array_slots[] = { "fill-pointer:   ",
440     "fill-pointer-p: ",
441     "elements:       ",
442     "data:           ",
443     "displacement:   ",
444     "displaced-p:    ",
445     /* Some reasonable number of dimensions */
446     "dimension 1:    ",
447     "dimension 2:    ",
448     "dimension 3:    ",
449     "dimension 4:    ",
450     "dimension 5:    ",
451     "dimension 6:    ",
452     "dimension 7:    ",
453     NULL
454 };
455
456 static char *simple_array_slots[] = { "length:   ",
457     NULL
458 };
459
460 #if (defined(i386) || defined(__x86_64))
461 static char *fn_slots[] =
462     { "inst start: ", "next: ", "name: ", "arglist: ", "type: ", NULL };
463 #else
464 static char *fn_slots[] =
465     { "self: ", "next: ", "name: ", "arglist: ", "type: ", NULL };
466 #endif
467
468 static char *closure_slots[] = { "fn: ", NULL };
469 static char *funcallable_instance_slots[] =
470     { "fn: ", "lexenv: ", "layout: ", NULL };
471 static char *weak_pointer_slots[] = { "value: ", "broken: ",
472 #ifdef GENCGC
473     "mark-bit: ",
474 #endif
475     NULL
476 };
477 static char *fdefn_slots[] = { "name: ", "function: ", "raw_addr: ", NULL };
478 static char *value_cell_slots[] = { "value: ", NULL };
479
480 #ifdef type_ScavengerHook
481 static char *scavenger_hook_slots[] =
482
483     { "value: ", "function: ", "next: ", NULL };
484 #endif
485
486 static void
487 print_otherptr(lispobj obj)
488 {
489     if (!valid_addr((os_vm_address_t) obj))
490         printf("(invalid address)");
491     else {
492 #ifndef alpha
493         unsigned long *ptr;
494         unsigned long header;
495         unsigned long length;
496 #else
497         u32 *ptr;
498         u32 header;
499         u32 length;
500 #endif
501         int count, type, index;
502         char buffer[16];
503
504 #ifndef alpha
505         ptr = (unsigned long *) PTR(obj);
506         if (ptr == (unsigned long *) NULL) {
507 #else
508         ptr = (u32 *) PTR(obj);
509         if (ptr == (u32 *) NULL) {
510 #endif
511             printf(" (NULL Pointer)");
512             return;
513         }
514
515         header = *ptr++;
516         length = fixnum_value(*ptr);
517         count = header >> 8;
518         type = TypeOf(header);
519
520         print_obj("header: ", header);
521         if (LowtagOf(header) != type_OtherImmediate0
522             && LowtagOf(header) != type_OtherImmediate1) {
523             NEWLINE;
524             printf("(invalid header object)");
525             return;
526         }
527
528         switch (type) {
529           case type_Bignum:
530               ptr += count;
531               NEWLINE;
532               printf("0x");
533               while (count-- > 0)
534                   printf("%08lx", *--ptr);
535               break;
536
537           case type_Ratio:
538               print_slots(ratio_slots, count, ptr);
539               break;
540
541           case type_Complex:
542               print_slots(complex_slots, count, ptr);
543               break;
544
545           case type_SymbolHeader:
546               print_slots(symbol_slots, count, ptr);
547               break;
548
549           case type_SingleFloat:
550               NEWLINE;
551               printf("%g", ((struct single_float *) PTR(obj))->value);
552               break;
553
554           case type_DoubleFloat:
555               NEWLINE;
556               printf("%.15lg", ((struct double_float *) PTR(obj))->value);
557               break;
558
559 #ifdef type_LongFloat
560           case type_LongFloat:
561               NEWLINE;
562               printf("%Lg", ((struct long_float *) PTR(obj))->value);
563               break;
564 #endif
565
566 #ifdef type_DoubleDoubleFloat
567           case type_DoubleDoubleFloat:
568               NEWLINE;
569               printf("%.15lg %.15lg", ((struct double_double_float *) PTR(obj))->hi,
570                      ((struct double_double_float *) PTR(obj))->lo);
571               break;
572 #endif              
573
574 #ifdef type_ComplexSingleFloat
575           case type_ComplexSingleFloat:
576               NEWLINE;
577               printf("%g", ((struct complex_single_float *) PTR(obj))->real);
578               NEWLINE;
579               printf("%g", ((struct complex_single_float *) PTR(obj))->imag);
580               break;
581 #endif
582
583 #ifdef type_ComplexDoubleFloat
584           case type_ComplexDoubleFloat:
585               NEWLINE;
586               printf("%.15lg", ((struct complex_double_float *) PTR(obj))->real);
587               NEWLINE;
588               printf("%.15lg", ((struct complex_double_float *) PTR(obj))->imag);
589               break;
590 #endif
591
592 #ifdef type_ComplexLongFloat
593           case type_ComplexLongFloat:
594               NEWLINE;
595               printf("%Lg", ((struct complex_long_float *) PTR(obj))->real);
596               NEWLINE;
597               printf("%Lg", ((struct complex_long_float *) PTR(obj))->imag);
598               break;
599 #endif
600
601 #ifdef type_ComplexDoubleDoubleFloat
602           case type_ComplexDoubleDoubleFloat:
603               NEWLINE;
604               printf("%.15lg %.15lg", ((struct complex_double_double_float *) PTR(obj))->real_hi,
605                      ((struct complex_double_double_float *) PTR(obj))->real_lo);
606               NEWLINE;
607               printf("%.15lg %.15lg", ((struct complex_double_double_float *) PTR(obj))->imag_hi,
608                      ((struct complex_double_double_float *) PTR(obj))->imag_lo);
609               break;
610 #endif
611
612
613           case type_SimpleString:
614               NEWLINE;
615               putchar('\"');
616               /* Need to back up one to get the start of the vector */
617               print_string((struct vector*) (ptr - 1));
618               putchar('\"');
619               break;
620
621           case type_SimpleVector:
622               NEWLINE;
623               printf("length = %ld", length);
624               ptr++;
625               index = 0;
626               while (length-- > 0) {
627                   sprintf(buffer, "%d: ", index++);
628                   print_obj(buffer, *ptr++);
629               }
630               break;
631
632           case type_InstanceHeader:
633               NEWLINE;
634               printf("length = %d", count);
635               index = 0;
636               while (count-- > 0) {
637                   sprintf(buffer, "%d: ", index++);
638                   print_obj(buffer, *ptr++);
639               }
640               break;
641
642           case type_SimpleArray:
643           case type_SimpleBitVector:
644           case type_SimpleArrayUnsignedByte2:
645           case type_SimpleArrayUnsignedByte4:
646           case type_SimpleArrayUnsignedByte8:
647           case type_SimpleArrayUnsignedByte16:
648           case type_SimpleArrayUnsignedByte32:
649 #ifdef type_SimpleArraySignedByte8
650           case type_SimpleArraySignedByte8:
651 #endif
652 #ifdef type_SimpleArraySignedByte16
653           case type_SimpleArraySignedByte16:
654 #endif
655 #ifdef type_SimpleArraySignedByte30
656           case type_SimpleArraySignedByte30:
657 #endif
658 #ifdef type_SimpleArraySignedByte32
659           case type_SimpleArraySignedByte32:
660 #endif
661           case type_SimpleArraySingleFloat:
662           case type_SimpleArrayDoubleFloat:
663 #ifdef type_SimpleArrayLongFloat
664           case type_SimpleArrayLongFloat:
665 #endif
666 #ifdef type_SimpleArrayDoubleDoubleFloat
667           case type_SimpleArrayDoubleDoubleFloat:
668 #endif
669 #ifdef type_SimpleArrayComplexSingleFloat
670           case type_SimpleArrayComplexSingleFloat:
671 #endif
672 #ifdef type_SimpleArrayComplexDoubleFloat
673           case type_SimpleArrayComplexDoubleFloat:
674 #endif
675 #ifdef type_SimpleArrayComplexLongFloat
676           case type_SimpleArrayComplexLongFloat:
677 #endif
678 #ifdef type_SimpleArrayComplexDoubleDoubleFloat
679           case type_SimpleArrayComplexDoubleDoubleFloat:
680 #endif
681               print_slots(simple_array_slots, 1, ptr);
682               break;
683           case type_ComplexString:
684           case type_ComplexBitVector:
685           case type_ComplexVector:
686           case type_ComplexArray:
687               print_slots(array_slots, count, ptr);
688               break;
689
690           case type_CodeHeader:
691               print_slots(code_slots, count - 1, ptr);
692               break;
693
694           case type_FunctionHeader:
695           case type_ClosureFunctionHeader:
696               print_slots(fn_slots, 5, ptr);
697               break;
698
699           case type_ReturnPcHeader:
700               print_obj("code: ", obj - (count * 4));
701               break;
702
703           case type_ClosureHeader:
704               print_slots(closure_slots, count, ptr);
705               break;
706
707           case type_FuncallableInstanceHeader:
708               print_slots(funcallable_instance_slots, count, ptr);
709               break;
710
711           case type_ValueCellHeader:
712               print_slots(value_cell_slots, 1, ptr);
713               break;
714
715           case type_Sap:
716               NEWLINE;
717 #ifndef alpha
718               printf("0x%08lx", *ptr);
719 #else
720               printf("0x%016lx", *(long *) (ptr + 1));
721 #endif
722               break;
723
724           case type_WeakPointer:
725               print_slots(weak_pointer_slots, 3, ptr);
726               break;
727
728           case type_BaseChar:
729           case type_UnboundMarker:
730               NEWLINE;
731               printf("pointer to an immediate?");
732               break;
733
734           case type_Fdefn:
735               print_slots(fdefn_slots, count, ptr);
736               break;
737
738 #ifdef type_ScavengerHook
739           case type_ScavengerHook:
740               print_slots(scavenger_hook_slots, count, ptr);
741               break;
742 #endif
743
744           default:
745               NEWLINE;
746               printf("Unknown header object?");
747               break;
748         }
749     }
750 }
751
752 static void
753 print_obj(char *prefix, lispobj obj)
754 {
755     static void (*verbose_fns[]) (lispobj obj)
756         = { print_fixnum, print_otherptr, print_otherimm, print_list,
757         print_fixnum, print_struct, print_otherimm, print_otherptr
758     };
759     static void (*brief_fns[]) (lispobj obj)
760         = { brief_fixnum, brief_otherptr, brief_otherimm, brief_list,
761         brief_fixnum, brief_struct, brief_otherimm, brief_otherptr
762     };
763     int type = LowtagOf(obj);
764     struct var *var = lookup_by_obj(obj);
765     char buffer[256];
766     boolean verbose = cur_depth < brief_depth;
767
768
769     if (!continue_p(verbose))
770         return;
771
772     if (var != NULL && var_clock(var) == cur_clock)
773         dont_decend = TRUE;
774
775     if (var == NULL
776         && (obj & type_FunctionPointer & type_ListPointer & type_InstancePointer
777             & type_OtherPointer) != 0)
778         var = define_var(NULL, obj, FALSE);
779
780     if (var != NULL)
781         var_setclock(var, cur_clock);
782
783     cur_depth++;
784     if (verbose) {
785         if (var != NULL) {
786             sprintf(buffer, "$%s=", var_name(var));
787             newline(buffer);
788         } else
789             newline(NULL);
790         printf("%s0x%08lx: ", prefix, obj);
791         if (cur_depth < brief_depth) {
792             fputs(lowtag_Names[type], stdout);
793             (*verbose_fns[type]) (obj);
794         } else
795             (*brief_fns[type]) (obj);
796     } else {
797         if (dont_decend)
798             printf("$%s", var_name(var));
799         else {
800             if (var != NULL)
801                 printf("$%s=", var_name(var));
802             (*brief_fns[type]) (obj);
803         }
804     }
805     cur_depth--;
806     dont_decend = FALSE;
807 }
808
809 void
810 reset_printer(void)
811 {
812     cur_clock++;
813     cur_lines = 0;
814     dont_decend = FALSE;
815 }
816
817 void
818 print(lispobj obj)
819 {
820     skip_newline = TRUE;
821     cur_depth = 0;
822     max_depth = 5;
823     max_lines = 20;
824
825     print_obj("", obj);
826
827     putchar('\n');
828 }
829
830 void
831 brief_print(lispobj obj)
832 {
833     skip_newline = TRUE;
834     cur_depth = 0;
835     max_depth = 1;
836     max_lines = 5000;
837
838     print_obj("", obj);
839     putchar('\n');
840 }