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 */
104 /* Multi-language support */
115 scm_option scm_print_opts
[] = {
116 { SCM_OPTION_SCM
, "closure-hook", SCM_BOOL_F
,
117 "Hook for printing closures." },
118 { SCM_OPTION_BOOLEAN
, "source", 0,
119 "Print closures with source." }
122 SCM_PROC (s_print_options
, "print-options-interface", 0, 1, 0, scm_print_options
);
125 scm_print_options (setting
)
128 SCM ans
= scm_options (setting
,
136 /* {Printing of Scheme Objects}
139 /* Detection of circular references.
141 * Due to other constraints in the implementation, this code has bad
142 * time complexity (O (depth * N)), The printer code will be
143 * completely rewritten before next release of Guile. The new code
146 #define PUSH_REF(pstate, obj) \
148 pstate->ref_stack[pstate->top++] = (obj); \
149 if (pstate->top == pstate->ceiling) \
150 grow_ref_stack (pstate); \
153 #define ENTER_NESTED_DATA(pstate, obj, label) \
155 register unsigned long i; \
156 for (i = 0; i < pstate->top; ++i) \
157 if (pstate->ref_stack[i] == (obj)) \
159 if (pstate->fancyp) \
161 if (pstate->top - pstate->list_offset >= pstate->level) \
163 scm_putc ('#', port); \
167 PUSH_REF(pstate, obj); \
170 #define EXIT_NESTED_DATA(pstate) { --pstate->top; }
172 SCM scm_print_state_vtable
;
174 static SCM print_state_pool
;
176 #ifdef GUILE_DEBUG /* Used for debugging purposes */
177 SCM_PROC(s_current_pstate
, "current-pstate", 0, 0, 0, scm_current_pstate
);
180 scm_current_pstate ()
182 return SCM_CADR (print_state_pool
);
186 #define PSTATE_SIZE 50L
188 static SCM make_print_state
SCM_P ((void));
193 SCM print_state
= scm_make_struct (SCM_CAR (print_state_pool
), /* pstate type */
196 scm_print_state
*pstate
= SCM_PRINT_STATE (print_state
);
197 pstate
->ref_vect
= scm_make_vector (SCM_MAKINUM (PSTATE_SIZE
),
199 pstate
->ref_stack
= SCM_VELTS (pstate
->ref_vect
);
200 pstate
->ceiling
= SCM_LENGTH (pstate
->ref_vect
);
205 scm_make_print_state ()
209 /* First try to allocate a print state from the pool */
211 if (SCM_NNULLP (SCM_CDR (print_state_pool
)))
213 answer
= SCM_CADR (print_state_pool
);
214 SCM_SETCDR (print_state_pool
, SCM_CDDR (print_state_pool
));
218 return answer
? answer
: make_print_state ();
221 static char s_print_state_printer
[] = "print-state-printer";
223 print_state_printer (obj
, port
)
227 /* This function can be made visible by means of struct-ref, so
228 we need to make sure that it gets what it wants. */
229 SCM_ASSERT (SCM_NIMP (obj
) && SCM_PRINT_STATE_P (obj
),
232 s_print_state_printer
);
233 SCM_ASSERT (scm_valid_oport_value_p (port
),
236 s_print_state_printer
);
237 port
= SCM_COERCE_OUTPORT (port
);
238 scm_puts ("#<print-state ", port
);
239 scm_intprint (obj
, 16, port
);
240 scm_putc ('>', port
);
241 return SCM_UNSPECIFIED
;
245 scm_free_print_state (print_state
)
249 scm_print_state
*pstate
= SCM_PRINT_STATE (print_state
);
250 /* Cleanup before returning print state to pool.
251 * It is better to do it here. Doing it in scm_prin1
252 * would cost more since that function is called much more
256 pstate
->revealed
= 0;
257 SCM_NEWCELL (handle
);
259 SCM_SETCAR (handle
, print_state
);
260 SCM_SETCDR (handle
, SCM_CDR (print_state_pool
));
261 SCM_SETCDR (print_state_pool
, handle
);
265 static void grow_ref_stack
SCM_P ((scm_print_state
*pstate
));
268 grow_ref_stack (pstate
)
269 scm_print_state
*pstate
;
271 int new_size
= 2 * pstate
->ceiling
;
272 scm_vector_set_length_x (pstate
->ref_vect
, SCM_MAKINUM (new_size
));
273 pstate
->ref_stack
= SCM_VELTS (pstate
->ref_vect
);
274 pstate
->ceiling
= new_size
;
278 static void print_circref
SCM_P ((SCM port
, scm_print_state
*pstate
, SCM ref
));
281 print_circref (port
, pstate
, ref
)
283 scm_print_state
*pstate
;
287 int self
= pstate
->top
- 1;
289 if (SCM_CONSP (pstate
->ref_stack
[i
]))
293 if (SCM_NCONSP (pstate
->ref_stack
[i
- 1])
294 || SCM_CDR (pstate
->ref_stack
[i
- 1]) != pstate
->ref_stack
[i
])
300 for (i
= pstate
->top
- 1; 1; --i
)
301 if (pstate
->ref_stack
[i
] == ref
)
303 scm_putc ('#', port
);
304 scm_intprint (i
- self
, 10, port
);
305 scm_putc ('#', port
);
308 /* Print generally. Handles both write and display according to PSTATE.
313 scm_iprin1 (exp
, port
, pstate
)
316 scm_print_state
*pstate
;
319 switch (7 & (int) exp
)
323 scm_intprint (SCM_INUM (exp
), 10, port
);
331 if (SCM_WRITINGP (pstate
))
333 scm_puts ("#\\", port
);
334 if ((i
>= 0) && (i
<= ' ') && scm_charnames
[i
])
335 scm_puts (scm_charnames
[i
], port
);
336 else if (i
< 0 || i
> '\177')
337 scm_intprint (i
, 8, port
);
344 else if (SCM_IFLAGP (exp
)
345 && ((size_t) SCM_ISYMNUM (exp
) < (sizeof scm_isymnames
/ sizeof (char *))))
346 scm_puts (SCM_ISYMCHARS (exp
), port
);
347 else if (SCM_ILOCP (exp
))
349 scm_puts ("#@", port
);
350 scm_intprint ((long) SCM_IFRAME (exp
), 10, port
);
351 scm_putc (SCM_ICDRP (exp
) ? '-' : '+', port
);
352 scm_intprint ((long) SCM_IDIST (exp
), 10, port
);
359 scm_puts ("#@", port
);
360 exp
= SCM_CAR (exp
- 1);
364 scm_ipruk ("immediate", exp
, port
);
367 switch (SCM_TYP7 (exp
))
369 case scm_tcs_cons_gloc
:
371 if (SCM_CDR (SCM_CAR (exp
) - 1L) == 0)
373 ENTER_NESTED_DATA (pstate
, exp
, circref
);
374 scm_print_struct (exp
, port
, pstate
);
375 EXIT_NESTED_DATA (pstate
);
379 case scm_tcs_cons_imcar
:
380 case scm_tcs_cons_nimcar
:
381 ENTER_NESTED_DATA (pstate
, exp
, circref
);
382 scm_iprlist ("(", exp
, ')', port
, pstate
);
383 EXIT_NESTED_DATA (pstate
);
386 print_circref (port
, pstate
, exp
);
389 if (!SCM_CLOSUREP (SCM_CDR (exp
)))
391 case scm_tcs_closures
:
392 /* The user supplied print closure procedure must handle
393 macro closures as well. */
394 if (SCM_FALSEP (scm_procedure_p (SCM_PRINT_CLOSURE
))
395 || SCM_FALSEP (scm_printer_apply (SCM_PRINT_CLOSURE
,
399 if (SCM_TYP16 (exp
) == scm_tc16_macro
)
401 /* Printing a macro. */
403 name
= scm_macro_name (exp
);
404 if (!SCM_CLOSUREP (SCM_CDR (exp
)))
407 scm_puts ("#<primitive-", port
);
411 code
= SCM_CODE (SCM_CDR (exp
));
412 env
= SCM_ENV (SCM_CDR (exp
));
413 scm_puts ("#<", port
);
415 if (SCM_CAR (exp
) & (3L << 16))
416 scm_puts ("macro", port
);
418 scm_puts ("syntax", port
);
419 if (SCM_CAR (exp
) & (2L << 16))
420 scm_putc ('!', port
);
424 /* Printing a closure. */
425 name
= scm_procedure_name (exp
);
426 code
= SCM_CODE (exp
);
428 scm_puts ("#<procedure", port
);
430 if (SCM_NIMP (name
) && SCM_ROSTRINGP (name
))
432 scm_putc (' ', port
);
433 scm_puts (SCM_ROCHARS (name
), port
);
437 if (SCM_PRINT_SOURCE_P
)
439 code
= scm_unmemocopy (code
,
440 SCM_EXTEND_ENV (SCM_CAR (code
),
443 ENTER_NESTED_DATA (pstate
, exp
, circref
);
444 scm_iprlist (" ", code
, '>', port
, pstate
);
445 EXIT_NESTED_DATA (pstate
);
449 if (SCM_TYP16 (exp
) != scm_tc16_macro
)
451 scm_putc (' ', port
);
452 scm_iprin1 (SCM_CAR (code
), port
, pstate
);
454 scm_putc ('>', port
);
458 scm_putc ('>', port
);
461 case scm_tc7_substring
:
463 if (SCM_WRITINGP (pstate
))
467 scm_putc ('"', port
);
468 for (i
= 0; i
< SCM_ROLENGTH (exp
); ++i
)
469 switch (SCM_ROCHARS (exp
)[i
])
473 scm_putc ('\\', port
);
475 scm_putc (SCM_ROCHARS (exp
)[i
], port
);
477 scm_putc ('"', port
);
481 scm_lfwrite (SCM_ROCHARS (exp
), (scm_sizet
) SCM_ROLENGTH (exp
),
484 case scm_tcs_symbols
:
494 len
= SCM_LENGTH (exp
);
495 str
= SCM_CHARS (exp
);
502 scm_lfwrite ("#{}#", 4, port
);
504 for (end
= pos
; end
< len
; ++end
)
507 #ifdef BRACKETS_AS_PARENS
515 case SCM_WHITE_SPACES
:
516 case SCM_LINE_INCREMENTORS
:
525 scm_lfwrite ("#{", 2, port
);
530 scm_lfwrite (str
+ pos
, end
- pos
, port
);
536 scm_lfwrite (buf
, 2, port
);
558 scm_lfwrite (str
+ pos
, end
- pos
, port
);
560 scm_lfwrite ("}#", 2, port
);
564 ENTER_NESTED_DATA (pstate
, exp
, circref
);
565 if (SCM_IS_WHVEC (exp
))
566 scm_puts ("#wh(", port
);
568 scm_puts ("#w(", port
);
569 goto common_vector_printer
;
572 ENTER_NESTED_DATA (pstate
, exp
, circref
);
573 scm_puts ("#(", port
);
574 common_vector_printer
:
577 int last
= SCM_LENGTH (exp
) - 1;
579 if (pstate
->fancyp
&& SCM_LENGTH (exp
) > pstate
->length
)
581 last
= pstate
->length
- 1;
584 for (i
= 0; i
< last
; ++i
)
587 scm_iprin1 (SCM_VELTS (exp
)[i
], port
, pstate
);
588 scm_putc (' ', port
);
593 scm_iprin1 (SCM_VELTS (exp
)[i
], port
, pstate
);
596 scm_puts (" ...", port
);
597 scm_putc (')', port
);
599 EXIT_NESTED_DATA (pstate
);
612 scm_raprin1 (exp
, port
, pstate
);
615 scm_puts ("#<primitive-procedure ", port
);
616 scm_puts (SCM_CHARS (SCM_SNAME (exp
)), port
);
617 scm_putc ('>', port
);
622 SCM proc
= SCM_CCLO_SUBR (exp
);
623 if (proc
== scm_f_gsubr_apply
)
625 /* Print gsubrs as primitives */
626 SCM name
= scm_procedure_name (exp
);
627 scm_puts ("#<primitive-procedure", port
);
628 if (SCM_NFALSEP (name
))
630 scm_putc (' ', port
);
631 scm_puts (SCM_CHARS (name
), port
);
636 scm_puts ("#<compiled-closure ", port
);
637 scm_iprin1 (proc
, port
, pstate
);
639 scm_putc ('>', port
);
644 scm_puts ("#<procedure-with-setter", port
);
646 SCM name
= scm_procedure_name (exp
);
647 if (SCM_NFALSEP (name
))
649 scm_putc (' ', port
);
650 scm_puts (SCM_ROCHARS (name
), port
);
653 scm_putc ('>', port
);
656 scm_puts ("#<continuation ", port
);
657 scm_intprint (SCM_LENGTH (exp
), 10, port
);
658 scm_puts (" @ ", port
);
659 scm_intprint ((long) SCM_CHARS (exp
), 16, port
);
660 scm_putc ('>', port
);
664 register long i
= SCM_PTOBNUM (exp
);
666 && scm_ptobs
[i
].print
667 && (scm_ptobs
[i
].print
) (exp
, port
, pstate
))
674 ENTER_NESTED_DATA (pstate
, exp
, circref
);
675 i
= SCM_SMOBNUM (exp
);
676 if (i
< scm_numsmob
&& scm_smobs
[i
].print
677 && (scm_smobs
[i
].print
) (exp
, port
, pstate
))
679 EXIT_NESTED_DATA (pstate
);
682 EXIT_NESTED_DATA (pstate
);
683 /* Macros have their print field set to NULL. They are
684 handled at the same place as closures in order to achieve
685 non-redundancy. Placing the condition here won't slow
686 down printing of other smobs. */
687 if (SCM_TYP16 (exp
) == scm_tc16_macro
)
692 scm_ipruk ("type", exp
, port
);
697 /* Print states are necessary for circular reference safe printing.
698 * They are also expensive to allocate. Therefore print states are
699 * kept in a pool so that they can be reused.
702 /* The PORT argument can also be a print-state/port pair, which will
703 * then be used instead of allocating a new print state. This is
704 * useful for continuing a chain of print calls from Scheme. */
707 scm_prin1 (exp
, port
, writingp
)
712 SCM handle
= SCM_BOOL_F
; /* Will GC protect the handle whilst unlinked */
714 scm_print_state
*pstate
;
716 /* If PORT is a print-state/port pair, use that. Else create a new
719 if (SCM_NIMP (port
) && SCM_CONSP (port
))
721 pstate_scm
= SCM_CDR (port
);
722 port
= SCM_CAR (port
);
726 /* First try to allocate a print state from the pool */
728 if (SCM_NNULLP (SCM_CDR (print_state_pool
)))
730 handle
= SCM_CDR (print_state_pool
);
731 SCM_SETCDR (print_state_pool
, SCM_CDDR (print_state_pool
));
734 if (handle
== SCM_BOOL_F
)
735 handle
= scm_cons (make_print_state (), SCM_EOL
);
736 pstate_scm
= SCM_CAR (handle
);
739 pstate
= SCM_PRINT_STATE (pstate_scm
);
740 pstate
->writingp
= writingp
;
741 scm_iprin1 (exp
, port
, pstate
);
743 /* Return print state to pool if it has been created above and
744 hasn't escaped to Scheme. */
746 if (handle
!= SCM_BOOL_F
&& !pstate
->revealed
)
749 SCM_SETCDR (handle
, SCM_CDR (print_state_pool
));
750 SCM_SETCDR (print_state_pool
, handle
);
760 scm_intprint (n
, radix
, port
)
765 char num_buf
[SCM_INTBUFLEN
];
766 scm_lfwrite (num_buf
, scm_iint2str (n
, radix
, num_buf
), port
);
769 /* Print an object of unrecognized type.
773 scm_ipruk (hdr
, ptr
, port
)
778 scm_puts ("#<unknown-", port
);
779 scm_puts (hdr
, port
);
782 scm_puts (" (0x", port
);
783 scm_intprint (SCM_CAR (ptr
), 16, port
);
784 scm_puts (" . 0x", port
);
785 scm_intprint (SCM_CDR (ptr
), 16, port
);
786 scm_puts (") @", port
);
788 scm_puts (" 0x", port
);
789 scm_intprint (ptr
, 16, port
);
790 scm_putc ('>', port
);
798 scm_iprlist (hdr
, exp
, tlr
, port
, pstate
)
803 scm_print_state
*pstate
;
805 register SCM hare
, tortoise
;
806 int floor
= pstate
->top
- 2;
807 scm_puts (hdr
, port
);
812 /* Run a hare and tortoise so that total time complexity will be
813 O(depth * N) instead of O(N^2). */
814 hare
= SCM_CDR (exp
);
816 while (SCM_NIMP (hare
) && SCM_ECONSP (hare
))
818 if (hare
== tortoise
)
820 hare
= SCM_CDR (hare
);
821 if (SCM_IMP (hare
) || SCM_NECONSP (hare
))
823 hare
= SCM_CDR (hare
);
824 tortoise
= SCM_CDR (tortoise
);
827 /* No cdr cycles intrinsic to this list */
828 scm_iprin1 (SCM_CAR (exp
), port
, pstate
);
830 for (; SCM_NIMP (exp
); exp
= SCM_CDR (exp
))
834 if (SCM_NECONSP (exp
))
836 for (i
= floor
; i
>= 0; --i
)
837 if (pstate
->ref_stack
[i
] == exp
)
839 PUSH_REF (pstate
, exp
);
840 scm_putc (' ', port
);
842 scm_iprin1 (SCM_CAR (exp
), port
, pstate
);
844 if (SCM_NNULLP (exp
))
846 scm_puts (" . ", port
);
847 scm_iprin1 (exp
, port
, pstate
);
851 scm_putc (tlr
, port
);
852 pstate
->top
= floor
+ 2;
857 int n
= pstate
->length
;
859 scm_iprin1 (SCM_CAR (exp
), port
, pstate
);
860 exp
= SCM_CDR (exp
); --n
;
861 for (; SCM_NIMP (exp
); exp
= SCM_CDR (exp
))
863 register unsigned long i
;
865 if (SCM_NECONSP (exp
))
867 for (i
= 0; i
< pstate
->top
; ++i
)
868 if (pstate
->ref_stack
[i
] == exp
)
874 scm_puts (" ...", port
);
880 PUSH_REF(pstate
, exp
);
881 ++pstate
->list_offset
;
882 scm_putc (' ', port
);
884 scm_iprin1 (SCM_CAR (exp
), port
, pstate
);
887 if (SCM_NNULLP (exp
))
889 scm_puts (" . ", port
);
890 scm_iprin1 (exp
, port
, pstate
);
893 pstate
->list_offset
-= pstate
->top
- floor
- 2;
897 pstate
->list_offset
-= pstate
->top
- floor
- 2;
900 scm_puts (" . ", port
);
901 print_circref (port
, pstate
, exp
);
908 scm_valid_oport_value_p (SCM val
)
910 return (SCM_NIMP (val
)
911 && (SCM_OPOUTPORTP (val
)
913 && SCM_NIMP (SCM_CAR (val
))
914 && SCM_OPOUTPORTP (SCM_CAR (val
))
915 && SCM_NIMP (SCM_CDR (val
))
916 && SCM_PRINT_STATE_P (SCM_CDR (val
)))));
919 SCM_PROC(s_write
, "write", 1, 1, 0, scm_write
);
922 scm_write (obj
, port
)
926 if (SCM_UNBNDP (port
))
929 SCM_ASSERT (scm_valid_oport_value_p (port
), port
, SCM_ARG2
, s_write
);
931 scm_prin1 (obj
, port
, 1);
935 scm_close_port (port
);
938 return SCM_UNSPECIFIED
;
942 SCM_PROC(s_display
, "display", 1, 1, 0, scm_display
);
945 scm_display (obj
, port
)
949 if (SCM_UNBNDP (port
))
952 SCM_ASSERT (scm_valid_oport_value_p (port
), port
, SCM_ARG2
, s_display
);
954 scm_prin1 (obj
, port
, 0);
958 scm_close_port (port
);
961 return SCM_UNSPECIFIED
;
964 SCM_PROC(s_newline
, "newline", 0, 1, 0, scm_newline
);
970 if (SCM_UNBNDP (port
))
973 SCM_ASSERT (scm_valid_oport_value_p (port
), port
, SCM_ARG1
, s_newline
);
975 scm_putc ('\n', SCM_COERCE_OUTPORT (port
));
976 return SCM_UNSPECIFIED
;
979 SCM_PROC(s_write_char
, "write-char", 1, 1, 0, scm_write_char
);
982 scm_write_char (chr
, port
)
986 if (SCM_UNBNDP (port
))
989 SCM_ASSERT (scm_valid_oport_value_p (port
), port
, SCM_ARG2
, s_write_char
);
991 SCM_ASSERT (SCM_ICHRP (chr
), chr
, SCM_ARG1
, s_write_char
);
992 scm_putc ((int) SCM_ICHR (chr
), SCM_COERCE_OUTPORT (port
));
996 scm_close_port (port
);
999 return SCM_UNSPECIFIED
;
1004 /* Call back to Scheme code to do the printing of special objects
1005 (like structs). SCM_PRINTER_APPLY applies PROC to EXP and a pair
1006 containing PORT and PSTATE. This pair can be used as the port for
1007 display/write etc to continue the current print chain. The REVEALED
1008 field of PSTATE is set to true to indicate that the print state has
1009 escaped to Scheme and thus has to be freed by the GC. */
1012 scm_printer_apply (proc
, exp
, port
, pstate
)
1013 SCM proc
, exp
, port
;
1014 scm_print_state
*pstate
;
1016 SCM pair
= scm_cons (port
, pstate
->handle
);
1017 pstate
->revealed
= 1;
1018 return scm_apply (proc
, exp
, scm_cons (pair
, scm_listofnull
));
1026 SCM vtable
, layout
, printer
, type
;
1028 scm_init_opts (scm_print_options
, scm_print_opts
, SCM_N_PRINT_OPTIONS
);
1029 vtable
= scm_make_vtable_vtable (scm_make_struct_layout (scm_nullstr
),
1032 layout
= scm_make_struct_layout (scm_makfrom0str (SCM_PRINT_STATE_LAYOUT
));
1033 printer
= scm_make_subr_opt (s_print_state_printer
,
1035 (SCM (*) ()) print_state_printer
,
1036 0 /* Don't bind the name. */);
1037 type
= scm_make_struct (vtable
, SCM_INUM0
, SCM_LIST2 (layout
, printer
));
1038 scm_set_struct_vtable_name_x (type
, SCM_CAR (scm_intern0 ("print-state")));
1039 print_state_pool
= scm_permanent_object (scm_cons (type
, SCM_EOL
));
1041 scm_print_state_vtable
= type
;