1 /* Copyright (C) 1995,1996,1997,1998 Free Software Foundation, Inc.
3 * This program is free software; you can redistribute it and/or modify
4 * it under the terms of the GNU General Public License as published by
5 * the Free Software Foundation; either version 2, or (at your option)
8 * This program is distributed in the hope that it will be useful,
9 * but WITHOUT ANY WARRANTY; without even the implied warranty of
10 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
11 * GNU General Public License for more details.
13 * You should have received a copy of the GNU General Public License
14 * along with this software; see the file COPYING. If not, write to
15 * the Free Software Foundation, Inc., 59 Temple Place, Suite 330,
16 * Boston, MA 02111-1307 USA
18 * As a special exception, the Free Software Foundation gives permission
19 * for additional uses of the text contained in its release of GUILE.
21 * The exception is that, if you link the GUILE library with other files
22 * to produce an executable, this does not by itself cause the
23 * resulting executable to be covered by the GNU General Public License.
24 * Your use of that executable is in no way restricted on account of
25 * linking the GUILE library code into it.
27 * This exception does not however invalidate any other reasons why
28 * the executable file might be covered by the GNU General Public License.
30 * This exception applies only to the code released by the
31 * Free Software Foundation under the name GUILE. If you copy
32 * code from other Free Software Foundation releases into a copy of
33 * GUILE, as the General Public License permits, the exception does
34 * not apply to the code that you add in this way. To avoid misleading
35 * anyone as to the status of such modified files, you must delete
36 * this exception notice from them.
38 * If you write modifications of your own for GUILE, it is your choice
39 * whether to permit this exception to apply to your modifications.
40 * If you do not wish that, delete this exception notice. */
60 /* {Names of immediate symbols}
62 * This table must agree with the declarations in scm.h: {Immediate Symbols}.
65 char *scm_isymnames
[] =
67 /* This table must agree with the declarations */
83 "#@literal-variable-ref",
84 "#@literal-variable-set!",
87 "#@call-with-current-continuation",
89 /* user visible ISYMS */
103 scm_option scm_print_opts
[] = {
104 { SCM_OPTION_SCM
, "closure-hook", SCM_BOOL_F
,
105 "Hook for printing closures." },
106 { SCM_OPTION_BOOLEAN
, "source", 0,
107 "Print closures with source." }
110 SCM_PROC (s_print_options
, "print-options-interface", 0, 1, 0, scm_print_options
);
113 scm_print_options (setting
)
116 SCM ans
= scm_options (setting
,
124 /* {Printing of Scheme Objects}
127 /* Detection of circular references.
129 * Due to other constraints in the implementation, this code has bad
130 * time complexity (O (depth * N)), The printer code will be
131 * completely rewritten before next release of Guile. The new code
134 #define PUSH_REF(pstate, obj) \
136 pstate->ref_stack[pstate->top++] = (obj); \
137 if (pstate->top == pstate->ceiling) \
138 grow_ref_stack (pstate); \
141 #define ENTER_NESTED_DATA(pstate, obj, label) \
143 register unsigned long i; \
144 for (i = 0; i < pstate->top; ++i) \
145 if (pstate->ref_stack[i] == (obj)) \
147 if (pstate->fancyp) \
149 if (pstate->top - pstate->list_offset >= pstate->level) \
151 scm_putc ('#', port); \
155 PUSH_REF(pstate, obj); \
158 #define EXIT_NESTED_DATA(pstate) { --pstate->top; }
160 SCM scm_print_state_vtable
;
162 static SCM print_state_pool
;
164 #ifdef GUILE_DEBUG /* Used for debugging purposes */
165 SCM_PROC(s_current_pstate
, "current-pstate", 0, 0, 0, scm_current_pstate
);
168 scm_current_pstate ()
170 return SCM_CADR (print_state_pool
);
174 #define PSTATE_SIZE 50L
176 static SCM make_print_state
SCM_P ((void));
181 SCM print_state
= scm_make_struct (SCM_CAR (print_state_pool
), /* pstate type */
184 scm_print_state
*pstate
= SCM_PRINT_STATE (print_state
);
185 pstate
->ref_vect
= scm_make_vector (SCM_MAKINUM (PSTATE_SIZE
),
187 pstate
->ref_stack
= SCM_VELTS (pstate
->ref_vect
);
188 pstate
->ceiling
= SCM_LENGTH (pstate
->ref_vect
);
193 scm_make_print_state ()
197 /* First try to allocate a print state from the pool */
199 if (SCM_NNULLP (SCM_CDR (print_state_pool
)))
201 answer
= SCM_CADR (print_state_pool
);
202 SCM_SETCDR (print_state_pool
, SCM_CDDR (print_state_pool
));
206 return answer
? answer
: make_print_state ();
209 static char s_print_state_printer
[] = "print-state-printer";
211 print_state_printer (obj
, port
)
215 /* This function can be made visible by means of struct-ref, so
216 we need to make sure that it gets what it wants. */
217 SCM_ASSERT (SCM_NIMP (obj
) && SCM_PRINT_STATE_P (obj
),
220 s_print_state_printer
);
221 SCM_ASSERT (scm_valid_oport_value_p (port
),
224 s_print_state_printer
);
225 port
= SCM_COERCE_OUTPORT (port
);
226 scm_puts ("#<print-state ", port
);
227 scm_intprint (obj
, 16, port
);
228 scm_putc ('>', port
);
229 return SCM_UNSPECIFIED
;
233 scm_free_print_state (print_state
)
237 scm_print_state
*pstate
= SCM_PRINT_STATE (print_state
);
238 /* Cleanup before returning print state to pool.
239 * It is better to do it here. Doing it in scm_prin1
240 * would cost more since that function is called much more
244 pstate
->revealed
= 0;
245 SCM_NEWCELL (handle
);
247 SCM_SETCAR (handle
, print_state
);
248 SCM_SETCDR (handle
, SCM_CDR (print_state_pool
));
249 SCM_SETCDR (print_state_pool
, handle
);
253 static void grow_ref_stack
SCM_P ((scm_print_state
*pstate
));
256 grow_ref_stack (pstate
)
257 scm_print_state
*pstate
;
259 int new_size
= 2 * pstate
->ceiling
;
260 scm_vector_set_length_x (pstate
->ref_vect
, SCM_MAKINUM (new_size
));
261 pstate
->ref_stack
= SCM_VELTS (pstate
->ref_vect
);
262 pstate
->ceiling
= new_size
;
266 static void print_circref
SCM_P ((SCM port
, scm_print_state
*pstate
, SCM ref
));
269 print_circref (port
, pstate
, ref
)
271 scm_print_state
*pstate
;
275 int self
= pstate
->top
- 1;
277 if (SCM_CONSP (pstate
->ref_stack
[i
]))
281 if (SCM_NCONSP (pstate
->ref_stack
[i
- 1])
282 || SCM_CDR (pstate
->ref_stack
[i
- 1]) != pstate
->ref_stack
[i
])
288 for (i
= pstate
->top
- 1; 1; --i
)
289 if (pstate
->ref_stack
[i
] == ref
)
291 scm_putc ('#', port
);
292 scm_intprint (i
- self
, 10, port
);
293 scm_putc ('#', port
);
296 /* Print generally. Handles both write and display according to PSTATE.
301 scm_iprin1 (exp
, port
, pstate
)
304 scm_print_state
*pstate
;
307 switch (7 & (int) exp
)
311 scm_intprint (SCM_INUM (exp
), 10, port
);
319 if (SCM_WRITINGP (pstate
))
321 scm_puts ("#\\", port
);
322 if ((i
>= 0) && (i
<= ' ') && scm_charnames
[i
])
323 scm_puts (scm_charnames
[i
], port
);
324 else if (i
< 0 || i
> '\177')
325 scm_intprint (i
, 8, port
);
332 else if (SCM_IFLAGP (exp
)
333 && ((size_t) SCM_ISYMNUM (exp
) < (sizeof scm_isymnames
/ sizeof (char *))))
334 scm_puts (SCM_ISYMCHARS (exp
), port
);
335 else if (SCM_ILOCP (exp
))
337 scm_puts ("#@", port
);
338 scm_intprint ((long) SCM_IFRAME (exp
), 10, port
);
339 scm_putc (SCM_ICDRP (exp
) ? '-' : '+', port
);
340 scm_intprint ((long) SCM_IDIST (exp
), 10, port
);
347 scm_puts ("#@", port
);
348 exp
= SCM_CAR (exp
- 1);
352 scm_ipruk ("immediate", exp
, port
);
355 switch (SCM_TYP7 (exp
))
357 case scm_tcs_cons_gloc
:
359 if (SCM_CDR (SCM_CAR (exp
) - 1L) == 0)
361 ENTER_NESTED_DATA (pstate
, exp
, circref
);
362 scm_print_struct (exp
, port
, pstate
);
363 EXIT_NESTED_DATA (pstate
);
367 case scm_tcs_cons_imcar
:
368 case scm_tcs_cons_nimcar
:
369 ENTER_NESTED_DATA (pstate
, exp
, circref
);
370 scm_iprlist ("(", exp
, ')', port
, pstate
);
371 EXIT_NESTED_DATA (pstate
);
374 print_circref (port
, pstate
, exp
);
377 if (!SCM_CLOSUREP (SCM_CDR (exp
)))
379 case scm_tcs_closures
:
380 /* The user supplied print closure procedure must handle
381 macro closures as well. */
382 if (SCM_FALSEP (scm_procedure_p (SCM_PRINT_CLOSURE
))
383 || SCM_FALSEP (scm_printer_apply (SCM_PRINT_CLOSURE
,
387 if (SCM_TYP16 (exp
) == scm_tc16_macro
)
389 /* Printing a macro. */
391 name
= scm_macro_name (exp
);
392 if (!SCM_CLOSUREP (SCM_CDR (exp
)))
395 scm_puts ("#<primitive-", port
);
399 code
= SCM_CODE (SCM_CDR (exp
));
400 env
= SCM_ENV (SCM_CDR (exp
));
401 scm_puts ("#<", port
);
403 if (SCM_CAR (exp
) & (3L << 16))
404 scm_puts ("macro", port
);
406 scm_puts ("syntax", port
);
407 if (SCM_CAR (exp
) & (2L << 16))
408 scm_putc ('!', port
);
412 /* Printing a closure. */
413 name
= scm_procedure_name (exp
);
414 code
= SCM_CODE (exp
);
416 scm_puts ("#<procedure", port
);
418 if (SCM_NIMP (name
) && SCM_ROSTRINGP (name
))
420 scm_putc (' ', port
);
421 scm_puts (SCM_ROCHARS (name
), port
);
425 if (SCM_PRINT_SOURCE_P
)
427 code
= scm_unmemocopy (code
,
428 SCM_EXTEND_ENV (SCM_CAR (code
),
431 ENTER_NESTED_DATA (pstate
, exp
, circref
);
432 scm_iprlist (" ", code
, '>', port
, pstate
);
433 EXIT_NESTED_DATA (pstate
);
437 if (SCM_TYP16 (exp
) != scm_tc16_macro
)
439 scm_putc (' ', port
);
440 scm_iprin1 (SCM_CAR (code
), port
, pstate
);
442 scm_putc ('>', port
);
446 scm_putc ('>', port
);
449 case scm_tc7_substring
:
451 if (SCM_WRITINGP (pstate
))
455 scm_putc ('"', port
);
456 for (i
= 0; i
< SCM_ROLENGTH (exp
); ++i
)
457 switch (SCM_ROCHARS (exp
)[i
])
461 scm_putc ('\\', port
);
463 scm_putc (SCM_ROCHARS (exp
)[i
], port
);
465 scm_putc ('"', port
);
469 scm_lfwrite (SCM_ROCHARS (exp
), (scm_sizet
) SCM_ROLENGTH (exp
),
472 case scm_tcs_symbols
:
482 len
= SCM_LENGTH (exp
);
483 str
= SCM_CHARS (exp
);
490 scm_lfwrite ("#{}#", 4, port
);
492 for (end
= pos
; end
< len
; ++end
)
495 #ifdef BRACKETS_AS_PARENS
503 case SCM_WHITE_SPACES
:
504 case SCM_LINE_INCREMENTORS
:
513 scm_lfwrite ("#{", 2, port
);
518 scm_lfwrite (str
+ pos
, end
- pos
, port
);
524 scm_lfwrite (buf
, 2, port
);
546 scm_lfwrite (str
+ pos
, end
- pos
, port
);
548 scm_lfwrite ("}#", 2, port
);
552 ENTER_NESTED_DATA (pstate
, exp
, circref
);
553 if (SCM_IS_WHVEC (exp
))
554 scm_puts ("#wh(", port
);
556 scm_puts ("#w(", port
);
557 goto common_vector_printer
;
560 ENTER_NESTED_DATA (pstate
, exp
, circref
);
561 scm_puts ("#(", port
);
562 common_vector_printer
:
565 int last
= SCM_LENGTH (exp
) - 1;
567 if (pstate
->fancyp
&& SCM_LENGTH (exp
) > pstate
->length
)
569 last
= pstate
->length
- 1;
572 for (i
= 0; i
< last
; ++i
)
575 scm_iprin1 (SCM_VELTS (exp
)[i
], port
, pstate
);
576 scm_putc (' ', port
);
581 scm_iprin1 (SCM_VELTS (exp
)[i
], port
, pstate
);
584 scm_puts (" ...", port
);
585 scm_putc (')', port
);
587 EXIT_NESTED_DATA (pstate
);
600 scm_raprin1 (exp
, port
, pstate
);
603 scm_puts ("#<primitive-procedure ", port
);
604 scm_puts (SCM_CHARS (SCM_SNAME (exp
)), port
);
605 scm_putc ('>', port
);
610 SCM proc
= SCM_CCLO_SUBR (exp
);
611 if (proc
== scm_f_gsubr_apply
)
613 /* Print gsubrs as primitives */
614 SCM name
= scm_procedure_name (exp
);
615 scm_puts ("#<primitive-procedure", port
);
616 if (SCM_NFALSEP (name
))
618 scm_putc (' ', port
);
619 scm_puts (SCM_CHARS (name
), port
);
624 scm_puts ("#<compiled-closure ", port
);
625 scm_iprin1 (proc
, port
, pstate
);
627 scm_putc ('>', port
);
632 scm_puts ("#<procedure-with-setter", port
);
634 SCM name
= scm_procedure_name (exp
);
635 if (SCM_NFALSEP (name
))
637 scm_putc (' ', port
);
638 scm_puts (SCM_ROCHARS (name
), port
);
641 scm_putc ('>', port
);
644 scm_puts ("#<continuation ", port
);
645 scm_intprint (SCM_LENGTH (exp
), 10, port
);
646 scm_puts (" @ ", port
);
647 scm_intprint ((long) SCM_CHARS (exp
), 16, port
);
648 scm_putc ('>', port
);
652 register long i
= SCM_PTOBNUM (exp
);
654 && scm_ptobs
[i
].print
655 && (scm_ptobs
[i
].print
) (exp
, port
, pstate
))
662 ENTER_NESTED_DATA (pstate
, exp
, circref
);
663 i
= SCM_SMOBNUM (exp
);
664 if (i
< scm_numsmob
&& scm_smobs
[i
].print
665 && (scm_smobs
[i
].print
) (exp
, port
, pstate
))
667 EXIT_NESTED_DATA (pstate
);
670 EXIT_NESTED_DATA (pstate
);
671 /* Macros have their print field set to NULL. They are
672 handled at the same place as closures in order to achieve
673 non-redundancy. Placing the condition here won't slow
674 down printing of other smobs. */
675 if (SCM_TYP16 (exp
) == scm_tc16_macro
)
680 scm_ipruk ("type", exp
, port
);
685 /* Print states are necessary for circular reference safe printing.
686 * They are also expensive to allocate. Therefore print states are
687 * kept in a pool so that they can be reused.
690 /* The PORT argument can also be a print-state/port pair, which will
691 * then be used instead of allocating a new print state. This is
692 * useful for continuing a chain of print calls from Scheme. */
695 scm_prin1 (exp
, port
, writingp
)
700 SCM handle
= SCM_BOOL_F
; /* Will GC protect the handle whilst unlinked */
702 scm_print_state
*pstate
;
704 /* If PORT is a print-state/port pair, use that. Else create a new
707 if (SCM_NIMP (port
) && SCM_CONSP (port
))
709 pstate_scm
= SCM_CDR (port
);
710 port
= SCM_CAR (port
);
714 /* First try to allocate a print state from the pool */
716 if (SCM_NNULLP (SCM_CDR (print_state_pool
)))
718 handle
= SCM_CDR (print_state_pool
);
719 SCM_SETCDR (print_state_pool
, SCM_CDDR (print_state_pool
));
722 if (handle
== SCM_BOOL_F
)
723 handle
= scm_cons (make_print_state (), SCM_EOL
);
724 pstate_scm
= SCM_CAR (handle
);
727 pstate
= SCM_PRINT_STATE (pstate_scm
);
728 pstate
->writingp
= writingp
;
729 scm_iprin1 (exp
, port
, pstate
);
731 /* Return print state to pool if it has been created above and
732 hasn't escaped to Scheme. */
734 if (handle
!= SCM_BOOL_F
&& !pstate
->revealed
)
737 SCM_SETCDR (handle
, SCM_CDR (print_state_pool
));
738 SCM_SETCDR (print_state_pool
, handle
);
748 scm_intprint (n
, radix
, port
)
753 char num_buf
[SCM_INTBUFLEN
];
754 scm_lfwrite (num_buf
, scm_iint2str (n
, radix
, num_buf
), port
);
757 /* Print an object of unrecognized type.
761 scm_ipruk (hdr
, ptr
, port
)
766 scm_puts ("#<unknown-", port
);
767 scm_puts (hdr
, port
);
770 scm_puts (" (0x", port
);
771 scm_intprint (SCM_CAR (ptr
), 16, port
);
772 scm_puts (" . 0x", port
);
773 scm_intprint (SCM_CDR (ptr
), 16, port
);
774 scm_puts (") @", port
);
776 scm_puts (" 0x", port
);
777 scm_intprint (ptr
, 16, port
);
778 scm_putc ('>', port
);
786 scm_iprlist (hdr
, exp
, tlr
, port
, pstate
)
791 scm_print_state
*pstate
;
793 register SCM hare
, tortoise
;
794 int floor
= pstate
->top
- 2;
795 scm_puts (hdr
, port
);
800 /* Run a hare and tortoise so that total time complexity will be
801 O(depth * N) instead of O(N^2). */
802 hare
= SCM_CDR (exp
);
804 while (SCM_NIMP (hare
) && SCM_ECONSP (hare
))
806 if (hare
== tortoise
)
808 hare
= SCM_CDR (hare
);
809 if (SCM_IMP (hare
) || SCM_NECONSP (hare
))
811 hare
= SCM_CDR (hare
);
812 tortoise
= SCM_CDR (tortoise
);
815 /* No cdr cycles intrinsic to this list */
816 scm_iprin1 (SCM_CAR (exp
), port
, pstate
);
818 for (; SCM_NIMP (exp
); exp
= SCM_CDR (exp
))
822 if (SCM_NECONSP (exp
))
824 for (i
= floor
; i
>= 0; --i
)
825 if (pstate
->ref_stack
[i
] == exp
)
827 PUSH_REF (pstate
, exp
);
828 scm_putc (' ', port
);
830 scm_iprin1 (SCM_CAR (exp
), port
, pstate
);
832 if (SCM_NNULLP (exp
))
834 scm_puts (" . ", port
);
835 scm_iprin1 (exp
, port
, pstate
);
839 scm_putc (tlr
, port
);
840 pstate
->top
= floor
+ 2;
845 int n
= pstate
->length
;
847 scm_iprin1 (SCM_CAR (exp
), port
, pstate
);
848 exp
= SCM_CDR (exp
); --n
;
849 for (; SCM_NIMP (exp
); exp
= SCM_CDR (exp
))
851 register unsigned long i
;
853 if (SCM_NECONSP (exp
))
855 for (i
= 0; i
< pstate
->top
; ++i
)
856 if (pstate
->ref_stack
[i
] == exp
)
862 scm_puts (" ...", port
);
868 PUSH_REF(pstate
, exp
);
869 ++pstate
->list_offset
;
870 scm_putc (' ', port
);
872 scm_iprin1 (SCM_CAR (exp
), port
, pstate
);
875 if (SCM_NNULLP (exp
))
877 scm_puts (" . ", port
);
878 scm_iprin1 (exp
, port
, pstate
);
881 pstate
->list_offset
-= pstate
->top
- floor
- 2;
885 pstate
->list_offset
-= pstate
->top
- floor
- 2;
888 scm_puts (" . ", port
);
889 print_circref (port
, pstate
, exp
);
896 scm_valid_oport_value_p (SCM val
)
898 return (SCM_NIMP (val
)
899 && (SCM_OPOUTPORTP (val
)
901 && SCM_NIMP (SCM_CAR (val
))
902 && SCM_OPOUTPORTP (SCM_CAR (val
))
903 && SCM_NIMP (SCM_CDR (val
))
904 && SCM_PRINT_STATE_P (SCM_CDR (val
)))));
907 SCM_PROC(s_write
, "write", 1, 1, 0, scm_write
);
910 scm_write (obj
, port
)
914 if (SCM_UNBNDP (port
))
917 SCM_ASSERT (scm_valid_oport_value_p (port
), port
, SCM_ARG2
, s_write
);
919 scm_prin1 (obj
, port
, 1);
923 scm_close_port (port
);
926 return SCM_UNSPECIFIED
;
930 SCM_PROC(s_display
, "display", 1, 1, 0, scm_display
);
933 scm_display (obj
, port
)
937 if (SCM_UNBNDP (port
))
940 SCM_ASSERT (scm_valid_oport_value_p (port
), port
, SCM_ARG2
, s_display
);
942 scm_prin1 (obj
, port
, 0);
946 scm_close_port (port
);
949 return SCM_UNSPECIFIED
;
952 SCM_PROC(s_newline
, "newline", 0, 1, 0, scm_newline
);
958 if (SCM_UNBNDP (port
))
961 SCM_ASSERT (scm_valid_oport_value_p (port
), port
, SCM_ARG1
, s_newline
);
963 scm_putc ('\n', SCM_COERCE_OUTPORT (port
));
967 scm_close_port (port
);
971 if (port
== scm_cur_outp
)
973 return SCM_UNSPECIFIED
;
976 SCM_PROC(s_write_char
, "write-char", 1, 1, 0, scm_write_char
);
979 scm_write_char (chr
, port
)
983 if (SCM_UNBNDP (port
))
986 SCM_ASSERT (scm_valid_oport_value_p (port
), port
, SCM_ARG2
, s_write_char
);
988 SCM_ASSERT (SCM_ICHRP (chr
), chr
, SCM_ARG1
, s_write_char
);
989 scm_putc ((int) SCM_ICHR (chr
), SCM_COERCE_OUTPORT (port
));
993 scm_close_port (port
);
996 return SCM_UNSPECIFIED
;
1001 /* Call back to Scheme code to do the printing of special objects
1002 (like structs). SCM_PRINTER_APPLY applies PROC to EXP and a pair
1003 containing PORT and PSTATE. This pair can be used as the port for
1004 display/write etc to continue the current print chain. The REVEALED
1005 field of PSTATE is set to true to indicate that the print state has
1006 escaped to Scheme and thus has to be freed by the GC. */
1009 scm_printer_apply (proc
, exp
, port
, pstate
)
1010 SCM proc
, exp
, port
;
1011 scm_print_state
*pstate
;
1013 SCM pair
= scm_cons (port
, pstate
->handle
);
1014 pstate
->revealed
= 1;
1015 return scm_apply (proc
, exp
, scm_cons (pair
, scm_listofnull
));
1023 SCM vtable
, layout
, printer
, type
;
1025 scm_init_opts (scm_print_options
, scm_print_opts
, SCM_N_PRINT_OPTIONS
);
1026 vtable
= scm_make_vtable_vtable (scm_make_struct_layout (scm_nullstr
),
1029 layout
= scm_make_struct_layout (scm_makfrom0str (SCM_PRINT_STATE_LAYOUT
));
1030 printer
= scm_make_subr_opt (s_print_state_printer
,
1032 (SCM (*) ()) print_state_printer
,
1033 0 /* Don't bind the name. */);
1034 type
= scm_make_struct (vtable
, SCM_INUM0
, SCM_LIST2 (layout
, printer
));
1035 print_state_pool
= scm_permanent_object (scm_cons (type
, SCM_EOL
));
1037 scm_print_state_vtable
= type
;