1 /* Copyright (C) 1995,1996,1997 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. */
59 /* {Names of immediate symbols}
61 * This table must agree with the declarations in scm.h: {Immediate Symbols}.
64 char *scm_isymnames
[] =
66 /* This table must agree with the declarations */
82 "#@literal-variable-ref",
83 "#@literal-variable-set!",
86 "#@call-with-current-continuation",
88 /* user visible ISYMS */
100 scm_option scm_print_opts
[] = {
101 { SCM_OPTION_SCM
, "closure-hook", SCM_BOOL_F
,
102 "Hook for printing closures." },
103 { SCM_OPTION_BOOLEAN
, "source", 0,
104 "Print closures with source." }
107 SCM_PROC (s_print_options
, "print-options-interface", 0, 1, 0, scm_print_options
);
110 scm_print_options (setting
)
113 SCM ans
= scm_options (setting
,
121 /* {Printing of Scheme Objects}
124 /* Detection of circular references.
126 * Due to other constraints in the implementation, this code has bad
127 * time complexity (O (depth * N)), The printer code will be
128 * completely rewritten before next release of Guile. The new code
131 #define PUSH_REF(pstate, obj) \
133 pstate->ref_stack[pstate->top++] = (obj); \
134 if (pstate->top == pstate->ceiling) \
135 grow_ref_stack (pstate); \
138 #define ENTER_NESTED_DATA(pstate, obj, label) \
141 for (i = 0; i < pstate->top; ++i) \
142 if (pstate->ref_stack[i] == (obj)) \
144 if (pstate->fancyp) \
146 if (pstate->top - pstate->list_offset >= pstate->level) \
148 scm_putc ('#', port); \
152 PUSH_REF(pstate, obj); \
155 #define EXIT_NESTED_DATA(pstate) { --pstate->top; }
157 SCM scm_print_state_vtable
;
159 static SCM print_state_pool
;
161 #ifdef GUILE_DEBUG /* Used for debugging purposes */
162 SCM_PROC(s_current_pstate
, "current-pstate", 0, 0, 0, scm_current_pstate
);
165 scm_current_pstate ()
167 return SCM_CADR (print_state_pool
);
171 #define PSTATE_SIZE 50L
173 static SCM make_print_state
SCM_P ((void));
178 SCM print_state
= scm_make_struct (SCM_CAR (print_state_pool
), /* pstate type */
181 scm_print_state
*pstate
= SCM_PRINT_STATE (print_state
);
182 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
;
306 switch (7 & (int) exp
)
310 scm_intprint (SCM_INUM (exp
), 10, port
);
316 if (SCM_WRITINGP (pstate
))
318 scm_puts ("#\\", port
);
319 if ((i
>= 0) && (i
<= ' ') && scm_charnames
[i
])
320 scm_puts (scm_charnames
[i
], port
);
321 else if (i
< 0 || i
> '\177')
322 scm_intprint (i
, 8, port
);
329 else if (SCM_IFLAGP (exp
)
330 && (SCM_ISYMNUM (exp
) < (sizeof scm_isymnames
/ sizeof (char *))))
331 scm_puts (SCM_ISYMCHARS (exp
), port
);
332 else if (SCM_ILOCP (exp
))
334 scm_puts ("#@", port
);
335 scm_intprint ((long) SCM_IFRAME (exp
), 10, port
);
336 scm_putc (SCM_ICDRP (exp
) ? '-' : '+', port
);
337 scm_intprint ((long) SCM_IDIST (exp
), 10, port
);
344 scm_puts ("#@", port
);
345 exp
= SCM_CAR (exp
- 1);
349 scm_ipruk ("immediate", exp
, port
);
352 switch (SCM_TYP7 (exp
))
354 case scm_tcs_cons_gloc
:
356 if (SCM_CDR (SCM_CAR (exp
) - 1L) == 0)
358 ENTER_NESTED_DATA (pstate
, exp
, circref
);
359 scm_print_struct (exp
, port
, pstate
);
360 EXIT_NESTED_DATA (pstate
);
364 case scm_tcs_cons_imcar
:
365 case scm_tcs_cons_nimcar
:
366 ENTER_NESTED_DATA (pstate
, exp
, circref
);
367 scm_iprlist ("(", exp
, ')', port
, pstate
);
368 EXIT_NESTED_DATA (pstate
);
371 print_circref (port
, pstate
, exp
);
374 if (!SCM_CLOSUREP (SCM_CDR (exp
)))
376 case scm_tcs_closures
:
377 /* The user supplied print closure procedure must handle
378 macro closures as well. */
379 if (SCM_FALSEP (scm_procedure_p (SCM_PRINT_CLOSURE
))
380 || SCM_FALSEP (scm_printer_apply (SCM_PRINT_CLOSURE
,
381 exp
, port
, pstate
)));
384 if (SCM_TYP16 (exp
) == scm_tc16_macro
)
386 /* Printing a macro. */
388 name
= scm_macro_name (exp
);
389 if (!SCM_CLOSUREP (SCM_CDR (exp
)))
392 scm_puts ("#<primitive-", port
);
396 code
= SCM_CODE (SCM_CDR (exp
));
397 env
= SCM_ENV (SCM_CDR (exp
));
398 scm_puts ("#<", port
);
400 if (SCM_CAR (exp
) & (3L << 16))
401 scm_puts ("macro", port
);
403 scm_puts ("syntax", port
);
404 if (SCM_CAR (exp
) & (2L << 16))
405 scm_putc ('!', port
);
409 /* Printing a closure. */
410 name
= scm_procedure_name (exp
);
411 code
= SCM_CODE (exp
);
413 scm_puts ("#<procedure", port
);
415 if (SCM_NIMP (name
) && SCM_ROSTRINGP (name
))
417 scm_putc (' ', port
);
418 scm_puts (SCM_ROCHARS (name
), port
);
422 if (SCM_PRINT_SOURCE_P
)
424 code
= scm_unmemocopy (code
,
425 SCM_EXTEND_ENV (SCM_CAR (code
),
428 ENTER_NESTED_DATA (pstate
, exp
, circref
);
429 scm_iprlist (" ", code
, '>', port
, pstate
);
430 EXIT_NESTED_DATA (pstate
);
434 if (SCM_TYP16 (exp
) != scm_tc16_macro
)
436 scm_putc (' ', port
);
437 scm_iprin1 (SCM_CAR (code
), port
, pstate
);
439 scm_putc ('>', port
);
443 scm_putc ('>', port
);
446 case scm_tc7_substring
:
448 if (SCM_WRITINGP (pstate
))
450 scm_putc ('"', port
);
451 for (i
= 0; i
< SCM_ROLENGTH (exp
); ++i
)
452 switch (SCM_ROCHARS (exp
)[i
])
456 scm_putc ('\\', port
);
458 scm_putc (SCM_ROCHARS (exp
)[i
], port
);
460 scm_putc ('"', port
);
464 scm_lfwrite (SCM_ROCHARS (exp
), (scm_sizet
) SCM_ROLENGTH (exp
),
467 case scm_tcs_symbols
:
477 len
= SCM_LENGTH (exp
);
478 str
= SCM_CHARS (exp
);
485 scm_lfwrite ("#{}#", 4, port
);
487 for (end
= pos
; end
< len
; ++end
)
490 #ifdef BRACKETS_AS_PARENS
498 case SCM_WHITE_SPACES
:
499 case SCM_LINE_INCREMENTORS
:
508 scm_lfwrite ("#{", 2, port
);
513 scm_lfwrite (str
+ pos
, end
- pos
, port
);
519 scm_lfwrite (buf
, 2, port
);
541 scm_lfwrite (str
+ pos
, end
- pos
, port
);
543 scm_lfwrite ("}#", 2, port
);
547 ENTER_NESTED_DATA (pstate
, exp
, circref
);
548 if (SCM_IS_WHVEC (exp
))
549 scm_puts ("#wh(", port
);
551 scm_puts ("#w(", port
);
552 goto common_vector_printer
;
555 ENTER_NESTED_DATA (pstate
, exp
, circref
);
556 scm_puts ("#(", port
);
557 common_vector_printer
:
559 int last
= SCM_LENGTH (exp
) - 1;
561 if (pstate
->fancyp
&& SCM_LENGTH (exp
) > pstate
->length
)
563 last
= pstate
->length
- 1;
566 for (i
= 0; i
< last
; ++i
)
569 scm_iprin1 (SCM_VELTS (exp
)[i
], port
, pstate
);
570 scm_putc (' ', port
);
575 scm_iprin1 (SCM_VELTS (exp
)[i
], port
, pstate
);
578 scm_puts (" ...", port
);
579 scm_putc (')', port
);
581 EXIT_NESTED_DATA (pstate
);
594 scm_raprin1 (exp
, port
, pstate
);
597 scm_puts ("#<primitive-procedure ", port
);
598 scm_puts (SCM_CHARS (SCM_SNAME (exp
)), port
);
599 scm_putc ('>', port
);
603 scm_puts ("#<compiled-closure ", port
);
604 scm_iprin1 (SCM_CCLO_SUBR (exp
), port
, pstate
);
605 scm_putc ('>', port
);
609 scm_puts ("#<continuation ", port
);
610 scm_intprint (SCM_LENGTH (exp
), 10, port
);
611 scm_puts (" @ ", port
);
612 scm_intprint ((long) SCM_CHARS (exp
), 16, port
);
613 scm_putc ('>', port
);
616 i
= SCM_PTOBNUM (exp
);
618 && scm_ptobs
[i
].print
619 && (scm_ptobs
[i
].print
) (exp
, port
, pstate
))
623 ENTER_NESTED_DATA (pstate
, exp
, circref
);
624 i
= SCM_SMOBNUM (exp
);
625 if (i
< scm_numsmob
&& scm_smobs
[i
].print
626 && (scm_smobs
[i
].print
) (exp
, port
, pstate
))
628 EXIT_NESTED_DATA (pstate
);
631 EXIT_NESTED_DATA (pstate
);
632 /* Macros have their print field set to NULL. They are
633 handled at the same place as closures in order to achieve
634 non-redundancy. Placing the condition here won't slow
635 down printing of other smobs. */
636 if (SCM_TYP16 (exp
) == scm_tc16_macro
)
640 scm_ipruk ("type", exp
, port
);
645 /* Print states are necessary for circular reference safe printing.
646 * They are also expensive to allocate. Therefore print states are
647 * kept in a pool so that they can be reused.
650 /* The PORT argument can also be a print-state/port pair, which will
651 * then be used instead of allocating a new print state. This is
652 * useful for continuing a chain of print calls from Scheme. */
655 scm_prin1 (exp
, port
, writingp
)
660 SCM handle
= SCM_BOOL_F
; /* Will GC protect the handle whilst unlinked */
662 scm_print_state
*pstate
;
664 /* If PORT is a print-state/port pair, use that. Else create a new
667 if (SCM_NIMP (port
) && SCM_CONSP (port
))
669 pstate_scm
= SCM_CDR (port
);
670 port
= SCM_CAR (port
);
674 /* First try to allocate a print state from the pool */
676 if (SCM_NNULLP (SCM_CDR (print_state_pool
)))
678 handle
= SCM_CDR (print_state_pool
);
679 SCM_SETCDR (print_state_pool
, SCM_CDDR (print_state_pool
));
682 if (handle
== SCM_BOOL_F
)
683 handle
= scm_cons (make_print_state (), SCM_EOL
);
684 pstate_scm
= SCM_CAR (handle
);
687 pstate
= SCM_PRINT_STATE (pstate_scm
);
688 pstate
->writingp
= writingp
;
689 scm_iprin1 (exp
, port
, pstate
);
691 /* Return print state to pool if it has been created above and
692 hasn't escaped to Scheme. */
694 if (handle
!= SCM_BOOL_F
&& !pstate
->revealed
)
697 SCM_SETCDR (handle
, SCM_CDR (print_state_pool
));
698 SCM_SETCDR (print_state_pool
, handle
);
708 scm_intprint (n
, radix
, port
)
713 char num_buf
[SCM_INTBUFLEN
];
714 scm_lfwrite (num_buf
, scm_iint2str (n
, radix
, num_buf
), port
);
717 /* Print an object of unrecognized type.
721 scm_ipruk (hdr
, ptr
, port
)
726 scm_puts ("#<unknown-", port
);
727 scm_puts (hdr
, port
);
730 scm_puts (" (0x", port
);
731 scm_intprint (SCM_CAR (ptr
), 16, port
);
732 scm_puts (" . 0x", port
);
733 scm_intprint (SCM_CDR (ptr
), 16, port
);
734 scm_puts (") @", port
);
736 scm_puts (" 0x", port
);
737 scm_intprint (ptr
, 16, port
);
738 scm_putc ('>', port
);
746 scm_iprlist (hdr
, exp
, tlr
, port
, pstate
)
751 scm_print_state
*pstate
;
754 register SCM hare
, tortoise
;
755 int floor
= pstate
->top
- 2;
756 scm_puts (hdr
, port
);
761 /* Run a hare and tortoise so that total time complexity will be
762 O(depth * N) instead of O(N^2). */
763 hare
= SCM_CDR (exp
);
765 while (SCM_NIMP (hare
) && SCM_ECONSP (hare
))
767 if (hare
== tortoise
)
769 hare
= SCM_CDR (hare
);
770 if (SCM_IMP (hare
) || SCM_NECONSP (hare
))
772 hare
= SCM_CDR (hare
);
773 tortoise
= SCM_CDR (tortoise
);
776 /* No cdr cycles intrinsic to this list */
777 scm_iprin1 (SCM_CAR (exp
), port
, pstate
);
779 for (; SCM_NIMP (exp
); exp
= SCM_CDR (exp
))
781 if (SCM_NECONSP (exp
))
783 for (i
= floor
; i
>= 0; --i
)
784 if (pstate
->ref_stack
[i
] == exp
)
786 PUSH_REF (pstate
, exp
);
787 scm_putc (' ', port
);
789 scm_iprin1 (SCM_CAR (exp
), port
, pstate
);
791 if (SCM_NNULLP (exp
))
793 scm_puts (" . ", port
);
794 scm_iprin1 (exp
, port
, pstate
);
798 scm_putc (tlr
, port
);
799 pstate
->top
= floor
+ 2;
804 int n
= pstate
->length
;
806 scm_iprin1 (SCM_CAR (exp
), port
, pstate
);
807 exp
= SCM_CDR (exp
); --n
;
808 for (; SCM_NIMP (exp
); exp
= SCM_CDR (exp
))
810 if (SCM_NECONSP (exp
))
812 for (i
= 0; i
< pstate
->top
; ++i
)
813 if (pstate
->ref_stack
[i
] == exp
)
819 scm_puts (" ...", port
);
825 PUSH_REF(pstate
, exp
);
826 ++pstate
->list_offset
;
827 scm_putc (' ', port
);
829 scm_iprin1 (SCM_CAR (exp
), port
, pstate
);
832 if (SCM_NNULLP (exp
))
834 scm_puts (" . ", port
);
835 scm_iprin1 (exp
, port
, pstate
);
838 pstate
->list_offset
-= pstate
->top
- floor
- 2;
842 pstate
->list_offset
-= pstate
->top
- floor
- 2;
845 scm_puts (" . ", port
);
846 print_circref (port
, pstate
, exp
);
853 scm_valid_oport_value_p (SCM val
)
855 return (SCM_NIMP (val
)
856 && (SCM_OPOUTPORTP (val
)
858 && SCM_NIMP (SCM_CAR (val
))
859 && SCM_OPOUTPORTP (SCM_CAR (val
))
860 && SCM_NIMP (SCM_CDR (val
))
861 && SCM_PRINT_STATE_P (SCM_CDR (val
)))));
864 SCM_PROC(s_write
, "write", 1, 1, 0, scm_write
);
867 scm_write (obj
, port
)
871 if (SCM_UNBNDP (port
))
874 SCM_ASSERT (scm_valid_oport_value_p (port
), port
, SCM_ARG2
, s_write
);
876 scm_prin1 (obj
, port
, 1);
880 scm_close_port (port
);
883 return SCM_UNSPECIFIED
;
887 SCM_PROC(s_display
, "display", 1, 1, 0, scm_display
);
890 scm_display (obj
, port
)
894 if (SCM_UNBNDP (port
))
897 SCM_ASSERT (scm_valid_oport_value_p (port
), port
, SCM_ARG2
, s_display
);
899 scm_prin1 (obj
, port
, 0);
903 scm_close_port (port
);
906 return SCM_UNSPECIFIED
;
909 SCM_PROC(s_newline
, "newline", 0, 1, 0, scm_newline
);
915 if (SCM_UNBNDP (port
))
918 SCM_ASSERT (scm_valid_oport_value_p (port
), port
, SCM_ARG1
, s_newline
);
920 scm_putc ('\n', SCM_COERCE_OUTPORT (port
));
924 scm_close_port (port
);
928 if (port
== scm_cur_outp
)
930 return SCM_UNSPECIFIED
;
933 SCM_PROC(s_write_char
, "write-char", 1, 1, 0, scm_write_char
);
936 scm_write_char (chr
, port
)
940 if (SCM_UNBNDP (port
))
943 SCM_ASSERT (scm_valid_oport_value_p (port
), port
, SCM_ARG2
, s_write_char
);
945 SCM_ASSERT (SCM_ICHRP (chr
), chr
, SCM_ARG1
, s_write_char
);
946 scm_putc ((int) SCM_ICHR (chr
), SCM_COERCE_OUTPORT (port
));
950 scm_close_port (port
);
953 return SCM_UNSPECIFIED
;
958 /* Call back to Scheme code to do the printing of special objects
959 (like structs). SCM_PRINTER_APPLY applies PROC to EXP and a pair
960 containing PORT and PSTATE. This pair can be used as the port for
961 display/write etc to continue the current print chain. The REVEALED
962 field of PSTATE is set to true to indicate that the print state has
963 escaped to Scheme and thus has to be freed by the GC. */
966 scm_printer_apply (proc
, exp
, port
, pstate
)
968 scm_print_state
*pstate
;
970 SCM pair
= scm_cons (port
, pstate
->handle
);
971 pstate
->revealed
= 1;
972 return scm_apply (proc
, exp
, scm_cons (pair
, scm_listofnull
));
980 SCM vtable
, layout
, printer
, type
;
982 scm_init_opts (scm_print_options
, scm_print_opts
, SCM_N_PRINT_OPTIONS
);
983 vtable
= scm_make_vtable_vtable (scm_make_struct_layout (scm_nullstr
),
986 layout
= scm_make_struct_layout (scm_makfrom0str (SCM_PRINT_STATE_LAYOUT
));
987 printer
= scm_make_subr_opt (s_print_state_printer
,
989 (SCM (*) ()) print_state_printer
,
990 0 /* Don't bind the name. */);
991 type
= scm_make_struct (vtable
, SCM_INUM0
, SCM_LIST2 (layout
, printer
));
992 print_state_pool
= scm_permanent_object (scm_cons (type
, SCM_EOL
));
994 scm_print_state_vtable
= type
;