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 */
101 scm_option scm_print_opts
[] = {
102 { SCM_OPTION_SCM
, "closure-hook", SCM_BOOL_F
,
103 "Hook for printing closures." },
104 { SCM_OPTION_BOOLEAN
, "source", 0,
105 "Print closures with source." }
108 SCM_PROC (s_print_options
, "print-options-interface", 0, 1, 0, scm_print_options
);
111 scm_print_options (setting
)
114 SCM ans
= scm_options (setting
,
122 /* {Printing of Scheme Objects}
125 /* Detection of circular references.
127 * Due to other constraints in the implementation, this code has bad
128 * time complexity (O (depth * N)), The printer code will be
129 * completely rewritten before next release of Guile. The new code
132 #define PUSH_REF(pstate, obj) \
134 pstate->ref_stack[pstate->top++] = (obj); \
135 if (pstate->top == pstate->ceiling) \
136 grow_ref_stack (pstate); \
139 #define ENTER_NESTED_DATA(pstate, obj, label) \
141 register unsigned long i; \
142 for (i = 0; i < pstate->top; ++i) \
143 if (pstate->ref_stack[i] == (obj)) \
145 if (pstate->fancyp) \
147 if (pstate->top - pstate->list_offset >= pstate->level) \
149 scm_putc ('#', port); \
153 PUSH_REF(pstate, obj); \
156 #define EXIT_NESTED_DATA(pstate) { --pstate->top; }
158 SCM scm_print_state_vtable
;
160 static SCM print_state_pool
;
162 #ifdef GUILE_DEBUG /* Used for debugging purposes */
163 SCM_PROC(s_current_pstate
, "current-pstate", 0, 0, 0, scm_current_pstate
);
166 scm_current_pstate ()
168 return SCM_CADR (print_state_pool
);
172 #define PSTATE_SIZE 50L
174 static SCM make_print_state
SCM_P ((void));
179 SCM print_state
= scm_make_struct (SCM_CAR (print_state_pool
), /* pstate type */
182 scm_print_state
*pstate
= SCM_PRINT_STATE (print_state
);
183 pstate
->ref_vect
= scm_make_vector (SCM_MAKINUM (PSTATE_SIZE
),
185 pstate
->ref_stack
= SCM_VELTS (pstate
->ref_vect
);
186 pstate
->ceiling
= SCM_LENGTH (pstate
->ref_vect
);
191 scm_make_print_state ()
195 /* First try to allocate a print state from the pool */
197 if (SCM_NNULLP (SCM_CDR (print_state_pool
)))
199 answer
= SCM_CADR (print_state_pool
);
200 SCM_SETCDR (print_state_pool
, SCM_CDDR (print_state_pool
));
204 return answer
? answer
: make_print_state ();
207 static char s_print_state_printer
[] = "print-state-printer";
209 print_state_printer (obj
, port
)
213 /* This function can be made visible by means of struct-ref, so
214 we need to make sure that it gets what it wants. */
215 SCM_ASSERT (SCM_NIMP (obj
) && SCM_PRINT_STATE_P (obj
),
218 s_print_state_printer
);
219 SCM_ASSERT (scm_valid_oport_value_p (port
),
222 s_print_state_printer
);
223 port
= SCM_COERCE_OUTPORT (port
);
224 scm_puts ("#<print-state ", port
);
225 scm_intprint (obj
, 16, port
);
226 scm_putc ('>', port
);
227 return SCM_UNSPECIFIED
;
231 scm_free_print_state (print_state
)
235 scm_print_state
*pstate
= SCM_PRINT_STATE (print_state
);
236 /* Cleanup before returning print state to pool.
237 * It is better to do it here. Doing it in scm_prin1
238 * would cost more since that function is called much more
242 pstate
->revealed
= 0;
243 SCM_NEWCELL (handle
);
245 SCM_SETCAR (handle
, print_state
);
246 SCM_SETCDR (handle
, SCM_CDR (print_state_pool
));
247 SCM_SETCDR (print_state_pool
, handle
);
251 static void grow_ref_stack
SCM_P ((scm_print_state
*pstate
));
254 grow_ref_stack (pstate
)
255 scm_print_state
*pstate
;
257 int new_size
= 2 * pstate
->ceiling
;
258 scm_vector_set_length_x (pstate
->ref_vect
, SCM_MAKINUM (new_size
));
259 pstate
->ref_stack
= SCM_VELTS (pstate
->ref_vect
);
260 pstate
->ceiling
= new_size
;
264 static void print_circref
SCM_P ((SCM port
, scm_print_state
*pstate
, SCM ref
));
267 print_circref (port
, pstate
, ref
)
269 scm_print_state
*pstate
;
273 int self
= pstate
->top
- 1;
275 if (SCM_CONSP (pstate
->ref_stack
[i
]))
279 if (SCM_NCONSP (pstate
->ref_stack
[i
- 1])
280 || SCM_CDR (pstate
->ref_stack
[i
- 1]) != pstate
->ref_stack
[i
])
286 for (i
= pstate
->top
- 1; 1; --i
)
287 if (pstate
->ref_stack
[i
] == ref
)
289 scm_putc ('#', port
);
290 scm_intprint (i
- self
, 10, port
);
291 scm_putc ('#', port
);
294 /* Print generally. Handles both write and display according to PSTATE.
299 scm_iprin1 (exp
, port
, pstate
)
302 scm_print_state
*pstate
;
305 switch (7 & (int) exp
)
309 scm_intprint (SCM_INUM (exp
), 10, port
);
317 if (SCM_WRITINGP (pstate
))
319 scm_puts ("#\\", port
);
320 if ((i
>= 0) && (i
<= ' ') && scm_charnames
[i
])
321 scm_puts (scm_charnames
[i
], port
);
322 else if (i
< 0 || i
> '\177')
323 scm_intprint (i
, 8, port
);
330 else if (SCM_IFLAGP (exp
)
331 && ((size_t) SCM_ISYMNUM (exp
) < (sizeof scm_isymnames
/ sizeof (char *))))
332 scm_puts (SCM_ISYMCHARS (exp
), port
);
333 else if (SCM_ILOCP (exp
))
335 scm_puts ("#@", port
);
336 scm_intprint ((long) SCM_IFRAME (exp
), 10, port
);
337 scm_putc (SCM_ICDRP (exp
) ? '-' : '+', port
);
338 scm_intprint ((long) SCM_IDIST (exp
), 10, port
);
345 scm_puts ("#@", port
);
346 exp
= SCM_CAR (exp
- 1);
350 scm_ipruk ("immediate", exp
, port
);
353 switch (SCM_TYP7 (exp
))
355 case scm_tcs_cons_gloc
:
357 if (SCM_CDR (SCM_CAR (exp
) - 1L) == 0)
359 ENTER_NESTED_DATA (pstate
, exp
, circref
);
360 scm_print_struct (exp
, port
, pstate
);
361 EXIT_NESTED_DATA (pstate
);
365 case scm_tcs_cons_imcar
:
366 case scm_tcs_cons_nimcar
:
367 ENTER_NESTED_DATA (pstate
, exp
, circref
);
368 scm_iprlist ("(", exp
, ')', port
, pstate
);
369 EXIT_NESTED_DATA (pstate
);
372 print_circref (port
, pstate
, exp
);
375 if (!SCM_CLOSUREP (SCM_CDR (exp
)))
377 case scm_tcs_closures
:
378 /* The user supplied print closure procedure must handle
379 macro closures as well. */
380 if (SCM_FALSEP (scm_procedure_p (SCM_PRINT_CLOSURE
))
381 || SCM_FALSEP (scm_printer_apply (SCM_PRINT_CLOSURE
,
385 if (SCM_TYP16 (exp
) == scm_tc16_macro
)
387 /* Printing a macro. */
389 name
= scm_macro_name (exp
);
390 if (!SCM_CLOSUREP (SCM_CDR (exp
)))
393 scm_puts ("#<primitive-", port
);
397 code
= SCM_CODE (SCM_CDR (exp
));
398 env
= SCM_ENV (SCM_CDR (exp
));
399 scm_puts ("#<", port
);
401 if (SCM_CAR (exp
) & (3L << 16))
402 scm_puts ("macro", port
);
404 scm_puts ("syntax", port
);
405 if (SCM_CAR (exp
) & (2L << 16))
406 scm_putc ('!', port
);
410 /* Printing a closure. */
411 name
= scm_procedure_name (exp
);
412 code
= SCM_CODE (exp
);
414 scm_puts ("#<procedure", port
);
416 if (SCM_NIMP (name
) && SCM_ROSTRINGP (name
))
418 scm_putc (' ', port
);
419 scm_puts (SCM_ROCHARS (name
), port
);
423 if (SCM_PRINT_SOURCE_P
)
425 code
= scm_unmemocopy (code
,
426 SCM_EXTEND_ENV (SCM_CAR (code
),
429 ENTER_NESTED_DATA (pstate
, exp
, circref
);
430 scm_iprlist (" ", code
, '>', port
, pstate
);
431 EXIT_NESTED_DATA (pstate
);
435 if (SCM_TYP16 (exp
) != scm_tc16_macro
)
437 scm_putc (' ', port
);
438 scm_iprin1 (SCM_CAR (code
), port
, pstate
);
440 scm_putc ('>', port
);
444 scm_putc ('>', port
);
447 case scm_tc7_substring
:
449 if (SCM_WRITINGP (pstate
))
453 scm_putc ('"', port
);
454 for (i
= 0; i
< SCM_ROLENGTH (exp
); ++i
)
455 switch (SCM_ROCHARS (exp
)[i
])
459 scm_putc ('\\', port
);
461 scm_putc (SCM_ROCHARS (exp
)[i
], port
);
463 scm_putc ('"', port
);
467 scm_lfwrite (SCM_ROCHARS (exp
), (scm_sizet
) SCM_ROLENGTH (exp
),
470 case scm_tcs_symbols
:
480 len
= SCM_LENGTH (exp
);
481 str
= SCM_CHARS (exp
);
488 scm_lfwrite ("#{}#", 4, port
);
490 for (end
= pos
; end
< len
; ++end
)
493 #ifdef BRACKETS_AS_PARENS
501 case SCM_WHITE_SPACES
:
502 case SCM_LINE_INCREMENTORS
:
511 scm_lfwrite ("#{", 2, port
);
516 scm_lfwrite (str
+ pos
, end
- pos
, port
);
522 scm_lfwrite (buf
, 2, port
);
544 scm_lfwrite (str
+ pos
, end
- pos
, port
);
546 scm_lfwrite ("}#", 2, port
);
550 ENTER_NESTED_DATA (pstate
, exp
, circref
);
551 if (SCM_IS_WHVEC (exp
))
552 scm_puts ("#wh(", port
);
554 scm_puts ("#w(", port
);
555 goto common_vector_printer
;
558 ENTER_NESTED_DATA (pstate
, exp
, circref
);
559 scm_puts ("#(", port
);
560 common_vector_printer
:
563 int last
= SCM_LENGTH (exp
) - 1;
565 if (pstate
->fancyp
&& SCM_LENGTH (exp
) > pstate
->length
)
567 last
= pstate
->length
- 1;
570 for (i
= 0; i
< last
; ++i
)
573 scm_iprin1 (SCM_VELTS (exp
)[i
], port
, pstate
);
574 scm_putc (' ', port
);
579 scm_iprin1 (SCM_VELTS (exp
)[i
], port
, pstate
);
582 scm_puts (" ...", port
);
583 scm_putc (')', port
);
585 EXIT_NESTED_DATA (pstate
);
598 scm_raprin1 (exp
, port
, pstate
);
601 scm_puts ("#<primitive-procedure ", port
);
602 scm_puts (SCM_CHARS (SCM_SNAME (exp
)), port
);
603 scm_putc ('>', port
);
608 SCM proc
= SCM_CCLO_SUBR (exp
);
609 if (proc
== scm_f_gsubr_apply
)
611 /* Print gsubrs as primitives */
612 SCM name
= scm_procedure_name (exp
);
613 scm_puts ("#<primitive-procedure", port
);
614 if (SCM_NFALSEP (name
))
616 scm_putc (' ', port
);
617 scm_puts (SCM_CHARS (name
), port
);
622 scm_puts ("#<compiled-closure ", port
);
623 scm_iprin1 (proc
, port
, pstate
);
625 scm_putc ('>', port
);
630 scm_puts ("#<procedure-with-setter", port
);
632 SCM name
= scm_procedure_name (exp
);
633 if (SCM_NFALSEP (name
))
635 scm_putc (' ', port
);
636 scm_puts (SCM_ROCHARS (name
), port
);
639 scm_putc ('>', port
);
642 scm_puts ("#<continuation ", port
);
643 scm_intprint (SCM_LENGTH (exp
), 10, port
);
644 scm_puts (" @ ", port
);
645 scm_intprint ((long) SCM_CHARS (exp
), 16, port
);
646 scm_putc ('>', port
);
650 register long i
= SCM_PTOBNUM (exp
);
652 && scm_ptobs
[i
].print
653 && (scm_ptobs
[i
].print
) (exp
, port
, pstate
))
660 ENTER_NESTED_DATA (pstate
, exp
, circref
);
661 i
= SCM_SMOBNUM (exp
);
662 if (i
< scm_numsmob
&& scm_smobs
[i
].print
663 && (scm_smobs
[i
].print
) (exp
, port
, pstate
))
665 EXIT_NESTED_DATA (pstate
);
668 EXIT_NESTED_DATA (pstate
);
669 /* Macros have their print field set to NULL. They are
670 handled at the same place as closures in order to achieve
671 non-redundancy. Placing the condition here won't slow
672 down printing of other smobs. */
673 if (SCM_TYP16 (exp
) == scm_tc16_macro
)
678 scm_ipruk ("type", exp
, port
);
683 /* Print states are necessary for circular reference safe printing.
684 * They are also expensive to allocate. Therefore print states are
685 * kept in a pool so that they can be reused.
688 /* The PORT argument can also be a print-state/port pair, which will
689 * then be used instead of allocating a new print state. This is
690 * useful for continuing a chain of print calls from Scheme. */
693 scm_prin1 (exp
, port
, writingp
)
698 SCM handle
= SCM_BOOL_F
; /* Will GC protect the handle whilst unlinked */
700 scm_print_state
*pstate
;
702 /* If PORT is a print-state/port pair, use that. Else create a new
705 if (SCM_NIMP (port
) && SCM_CONSP (port
))
707 pstate_scm
= SCM_CDR (port
);
708 port
= SCM_CAR (port
);
712 /* First try to allocate a print state from the pool */
714 if (SCM_NNULLP (SCM_CDR (print_state_pool
)))
716 handle
= SCM_CDR (print_state_pool
);
717 SCM_SETCDR (print_state_pool
, SCM_CDDR (print_state_pool
));
720 if (handle
== SCM_BOOL_F
)
721 handle
= scm_cons (make_print_state (), SCM_EOL
);
722 pstate_scm
= SCM_CAR (handle
);
725 pstate
= SCM_PRINT_STATE (pstate_scm
);
726 pstate
->writingp
= writingp
;
727 scm_iprin1 (exp
, port
, pstate
);
729 /* Return print state to pool if it has been created above and
730 hasn't escaped to Scheme. */
732 if (handle
!= SCM_BOOL_F
&& !pstate
->revealed
)
735 SCM_SETCDR (handle
, SCM_CDR (print_state_pool
));
736 SCM_SETCDR (print_state_pool
, handle
);
746 scm_intprint (n
, radix
, port
)
751 char num_buf
[SCM_INTBUFLEN
];
752 scm_lfwrite (num_buf
, scm_iint2str (n
, radix
, num_buf
), port
);
755 /* Print an object of unrecognized type.
759 scm_ipruk (hdr
, ptr
, port
)
764 scm_puts ("#<unknown-", port
);
765 scm_puts (hdr
, port
);
768 scm_puts (" (0x", port
);
769 scm_intprint (SCM_CAR (ptr
), 16, port
);
770 scm_puts (" . 0x", port
);
771 scm_intprint (SCM_CDR (ptr
), 16, port
);
772 scm_puts (") @", port
);
774 scm_puts (" 0x", port
);
775 scm_intprint (ptr
, 16, port
);
776 scm_putc ('>', port
);
784 scm_iprlist (hdr
, exp
, tlr
, port
, pstate
)
789 scm_print_state
*pstate
;
791 register SCM hare
, tortoise
;
792 int floor
= pstate
->top
- 2;
793 scm_puts (hdr
, port
);
798 /* Run a hare and tortoise so that total time complexity will be
799 O(depth * N) instead of O(N^2). */
800 hare
= SCM_CDR (exp
);
802 while (SCM_NIMP (hare
) && SCM_ECONSP (hare
))
804 if (hare
== tortoise
)
806 hare
= SCM_CDR (hare
);
807 if (SCM_IMP (hare
) || SCM_NECONSP (hare
))
809 hare
= SCM_CDR (hare
);
810 tortoise
= SCM_CDR (tortoise
);
813 /* No cdr cycles intrinsic to this list */
814 scm_iprin1 (SCM_CAR (exp
), port
, pstate
);
816 for (; SCM_NIMP (exp
); exp
= SCM_CDR (exp
))
820 if (SCM_NECONSP (exp
))
822 for (i
= floor
; i
>= 0; --i
)
823 if (pstate
->ref_stack
[i
] == exp
)
825 PUSH_REF (pstate
, exp
);
826 scm_putc (' ', port
);
828 scm_iprin1 (SCM_CAR (exp
), port
, pstate
);
830 if (SCM_NNULLP (exp
))
832 scm_puts (" . ", port
);
833 scm_iprin1 (exp
, port
, pstate
);
837 scm_putc (tlr
, port
);
838 pstate
->top
= floor
+ 2;
843 int n
= pstate
->length
;
845 scm_iprin1 (SCM_CAR (exp
), port
, pstate
);
846 exp
= SCM_CDR (exp
); --n
;
847 for (; SCM_NIMP (exp
); exp
= SCM_CDR (exp
))
849 register unsigned long i
;
851 if (SCM_NECONSP (exp
))
853 for (i
= 0; i
< pstate
->top
; ++i
)
854 if (pstate
->ref_stack
[i
] == exp
)
860 scm_puts (" ...", port
);
866 PUSH_REF(pstate
, exp
);
867 ++pstate
->list_offset
;
868 scm_putc (' ', port
);
870 scm_iprin1 (SCM_CAR (exp
), port
, pstate
);
873 if (SCM_NNULLP (exp
))
875 scm_puts (" . ", port
);
876 scm_iprin1 (exp
, port
, pstate
);
879 pstate
->list_offset
-= pstate
->top
- floor
- 2;
883 pstate
->list_offset
-= pstate
->top
- floor
- 2;
886 scm_puts (" . ", port
);
887 print_circref (port
, pstate
, exp
);
894 scm_valid_oport_value_p (SCM val
)
896 return (SCM_NIMP (val
)
897 && (SCM_OPOUTPORTP (val
)
899 && SCM_NIMP (SCM_CAR (val
))
900 && SCM_OPOUTPORTP (SCM_CAR (val
))
901 && SCM_NIMP (SCM_CDR (val
))
902 && SCM_PRINT_STATE_P (SCM_CDR (val
)))));
905 SCM_PROC(s_write
, "write", 1, 1, 0, scm_write
);
908 scm_write (obj
, port
)
912 if (SCM_UNBNDP (port
))
915 SCM_ASSERT (scm_valid_oport_value_p (port
), port
, SCM_ARG2
, s_write
);
917 scm_prin1 (obj
, port
, 1);
921 scm_close_port (port
);
924 return SCM_UNSPECIFIED
;
928 SCM_PROC(s_display
, "display", 1, 1, 0, scm_display
);
931 scm_display (obj
, port
)
935 if (SCM_UNBNDP (port
))
938 SCM_ASSERT (scm_valid_oport_value_p (port
), port
, SCM_ARG2
, s_display
);
940 scm_prin1 (obj
, port
, 0);
944 scm_close_port (port
);
947 return SCM_UNSPECIFIED
;
950 SCM_PROC(s_newline
, "newline", 0, 1, 0, scm_newline
);
956 if (SCM_UNBNDP (port
))
959 SCM_ASSERT (scm_valid_oport_value_p (port
), port
, SCM_ARG1
, s_newline
);
961 scm_putc ('\n', SCM_COERCE_OUTPORT (port
));
965 scm_close_port (port
);
969 if (port
== scm_cur_outp
)
971 return SCM_UNSPECIFIED
;
974 SCM_PROC(s_write_char
, "write-char", 1, 1, 0, scm_write_char
);
977 scm_write_char (chr
, port
)
981 if (SCM_UNBNDP (port
))
984 SCM_ASSERT (scm_valid_oport_value_p (port
), port
, SCM_ARG2
, s_write_char
);
986 SCM_ASSERT (SCM_ICHRP (chr
), chr
, SCM_ARG1
, s_write_char
);
987 scm_putc ((int) SCM_ICHR (chr
), SCM_COERCE_OUTPORT (port
));
991 scm_close_port (port
);
994 return SCM_UNSPECIFIED
;
999 /* Call back to Scheme code to do the printing of special objects
1000 (like structs). SCM_PRINTER_APPLY applies PROC to EXP and a pair
1001 containing PORT and PSTATE. This pair can be used as the port for
1002 display/write etc to continue the current print chain. The REVEALED
1003 field of PSTATE is set to true to indicate that the print state has
1004 escaped to Scheme and thus has to be freed by the GC. */
1007 scm_printer_apply (proc
, exp
, port
, pstate
)
1008 SCM proc
, exp
, port
;
1009 scm_print_state
*pstate
;
1011 SCM pair
= scm_cons (port
, pstate
->handle
);
1012 pstate
->revealed
= 1;
1013 return scm_apply (proc
, exp
, scm_cons (pair
, scm_listofnull
));
1021 SCM vtable
, layout
, printer
, type
;
1023 scm_init_opts (scm_print_options
, scm_print_opts
, SCM_N_PRINT_OPTIONS
);
1024 vtable
= scm_make_vtable_vtable (scm_make_struct_layout (scm_nullstr
),
1027 layout
= scm_make_struct_layout (scm_makfrom0str (SCM_PRINT_STATE_LAYOUT
));
1028 printer
= scm_make_subr_opt (s_print_state_printer
,
1030 (SCM (*) ()) print_state_printer
,
1031 0 /* Don't bind the name. */);
1032 type
= scm_make_struct (vtable
, SCM_INUM0
, SCM_LIST2 (layout
, printer
));
1033 print_state_pool
= scm_permanent_object (scm_cons (type
, SCM_EOL
));
1035 scm_print_state_vtable
= type
;