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