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) \
140 register unsigned long i; \
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
),
184 pstate
->ref_stack
= SCM_VELTS (pstate
->ref_vect
);
185 pstate
->ceiling
= SCM_LENGTH (pstate
->ref_vect
);
190 scm_make_print_state ()
194 /* First try to allocate a print state from the pool */
196 if (SCM_NNULLP (SCM_CDR (print_state_pool
)))
198 answer
= SCM_CADR (print_state_pool
);
199 SCM_SETCDR (print_state_pool
, SCM_CDDR (print_state_pool
));
203 return answer
? answer
: make_print_state ();
206 static char s_print_state_printer
[] = "print-state-printer";
208 print_state_printer (obj
, port
)
212 /* This function can be made visible by means of struct-ref, so
213 we need to make sure that it gets what it wants. */
214 SCM_ASSERT (SCM_NIMP (obj
) && SCM_PRINT_STATE_P (obj
),
217 s_print_state_printer
);
218 SCM_ASSERT (scm_valid_oport_value_p (port
),
221 s_print_state_printer
);
222 port
= SCM_COERCE_OUTPORT (port
);
223 scm_puts ("#<print-state ", port
);
224 scm_intprint (obj
, 16, port
);
225 scm_putc ('>', port
);
226 return SCM_UNSPECIFIED
;
230 scm_free_print_state (print_state
)
234 scm_print_state
*pstate
= SCM_PRINT_STATE (print_state
);
235 /* Cleanup before returning print state to pool.
236 * It is better to do it here. Doing it in scm_prin1
237 * would cost more since that function is called much more
241 pstate
->revealed
= 0;
242 SCM_NEWCELL (handle
);
244 SCM_SETCAR (handle
, print_state
);
245 SCM_SETCDR (handle
, SCM_CDR (print_state_pool
));
246 SCM_SETCDR (print_state_pool
, handle
);
250 static void grow_ref_stack
SCM_P ((scm_print_state
*pstate
));
253 grow_ref_stack (pstate
)
254 scm_print_state
*pstate
;
256 int new_size
= 2 * pstate
->ceiling
;
257 scm_vector_set_length_x (pstate
->ref_vect
, SCM_MAKINUM (new_size
));
258 pstate
->ref_stack
= SCM_VELTS (pstate
->ref_vect
);
259 pstate
->ceiling
= new_size
;
263 static void print_circref
SCM_P ((SCM port
, scm_print_state
*pstate
, SCM ref
));
266 print_circref (port
, pstate
, ref
)
268 scm_print_state
*pstate
;
272 int self
= pstate
->top
- 1;
274 if (SCM_CONSP (pstate
->ref_stack
[i
]))
278 if (SCM_NCONSP (pstate
->ref_stack
[i
- 1])
279 || SCM_CDR (pstate
->ref_stack
[i
- 1]) != pstate
->ref_stack
[i
])
285 for (i
= pstate
->top
- 1; 1; --i
)
286 if (pstate
->ref_stack
[i
] == ref
)
288 scm_putc ('#', port
);
289 scm_intprint (i
- self
, 10, port
);
290 scm_putc ('#', port
);
293 /* Print generally. Handles both write and display according to PSTATE.
298 scm_iprin1 (exp
, port
, pstate
)
301 scm_print_state
*pstate
;
304 switch (7 & (int) exp
)
308 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 && ((size_t) 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
))
452 scm_putc ('"', port
);
453 for (i
= 0; i
< SCM_ROLENGTH (exp
); ++i
)
454 switch (SCM_ROCHARS (exp
)[i
])
458 scm_putc ('\\', port
);
460 scm_putc (SCM_ROCHARS (exp
)[i
], port
);
462 scm_putc ('"', port
);
466 scm_lfwrite (SCM_ROCHARS (exp
), (scm_sizet
) SCM_ROLENGTH (exp
),
469 case scm_tcs_symbols
:
479 len
= SCM_LENGTH (exp
);
480 str
= SCM_CHARS (exp
);
487 scm_lfwrite ("#{}#", 4, port
);
489 for (end
= pos
; end
< len
; ++end
)
492 #ifdef BRACKETS_AS_PARENS
500 case SCM_WHITE_SPACES
:
501 case SCM_LINE_INCREMENTORS
:
510 scm_lfwrite ("#{", 2, port
);
515 scm_lfwrite (str
+ pos
, end
- pos
, port
);
521 scm_lfwrite (buf
, 2, port
);
543 scm_lfwrite (str
+ pos
, end
- pos
, port
);
545 scm_lfwrite ("}#", 2, port
);
549 ENTER_NESTED_DATA (pstate
, exp
, circref
);
550 if (SCM_IS_WHVEC (exp
))
551 scm_puts ("#wh(", port
);
553 scm_puts ("#w(", port
);
554 goto common_vector_printer
;
557 ENTER_NESTED_DATA (pstate
, exp
, circref
);
558 scm_puts ("#(", port
);
559 common_vector_printer
:
562 int last
= SCM_LENGTH (exp
) - 1;
564 if (pstate
->fancyp
&& SCM_LENGTH (exp
) > pstate
->length
)
566 last
= pstate
->length
- 1;
569 for (i
= 0; i
< last
; ++i
)
572 scm_iprin1 (SCM_VELTS (exp
)[i
], port
, pstate
);
573 scm_putc (' ', port
);
578 scm_iprin1 (SCM_VELTS (exp
)[i
], port
, pstate
);
581 scm_puts (" ...", port
);
582 scm_putc (')', port
);
584 EXIT_NESTED_DATA (pstate
);
597 scm_raprin1 (exp
, port
, pstate
);
600 scm_puts ("#<primitive-procedure ", port
);
601 scm_puts (SCM_CHARS (SCM_SNAME (exp
)), port
);
602 scm_putc ('>', port
);
606 scm_puts ("#<compiled-closure ", port
);
607 scm_iprin1 (SCM_CCLO_SUBR (exp
), port
, pstate
);
608 scm_putc ('>', port
);
612 scm_puts ("#<continuation ", port
);
613 scm_intprint (SCM_LENGTH (exp
), 10, port
);
614 scm_puts (" @ ", port
);
615 scm_intprint ((long) SCM_CHARS (exp
), 16, port
);
616 scm_putc ('>', port
);
620 register long i
= SCM_PTOBNUM (exp
);
622 && scm_ptobs
[i
].print
623 && (scm_ptobs
[i
].print
) (exp
, port
, pstate
))
630 ENTER_NESTED_DATA (pstate
, exp
, circref
);
631 i
= SCM_SMOBNUM (exp
);
632 if (i
< scm_numsmob
&& scm_smobs
[i
].print
633 && (scm_smobs
[i
].print
) (exp
, port
, pstate
))
635 EXIT_NESTED_DATA (pstate
);
638 EXIT_NESTED_DATA (pstate
);
639 /* Macros have their print field set to NULL. They are
640 handled at the same place as closures in order to achieve
641 non-redundancy. Placing the condition here won't slow
642 down printing of other smobs. */
643 if (SCM_TYP16 (exp
) == scm_tc16_macro
)
648 scm_ipruk ("type", exp
, port
);
653 /* Print states are necessary for circular reference safe printing.
654 * They are also expensive to allocate. Therefore print states are
655 * kept in a pool so that they can be reused.
658 /* The PORT argument can also be a print-state/port pair, which will
659 * then be used instead of allocating a new print state. This is
660 * useful for continuing a chain of print calls from Scheme. */
663 scm_prin1 (exp
, port
, writingp
)
668 SCM handle
= SCM_BOOL_F
; /* Will GC protect the handle whilst unlinked */
670 scm_print_state
*pstate
;
672 /* If PORT is a print-state/port pair, use that. Else create a new
675 if (SCM_NIMP (port
) && SCM_CONSP (port
))
677 pstate_scm
= SCM_CDR (port
);
678 port
= SCM_CAR (port
);
682 /* First try to allocate a print state from the pool */
684 if (SCM_NNULLP (SCM_CDR (print_state_pool
)))
686 handle
= SCM_CDR (print_state_pool
);
687 SCM_SETCDR (print_state_pool
, SCM_CDDR (print_state_pool
));
690 if (handle
== SCM_BOOL_F
)
691 handle
= scm_cons (make_print_state (), SCM_EOL
);
692 pstate_scm
= SCM_CAR (handle
);
695 pstate
= SCM_PRINT_STATE (pstate_scm
);
696 pstate
->writingp
= writingp
;
697 scm_iprin1 (exp
, port
, pstate
);
699 /* Return print state to pool if it has been created above and
700 hasn't escaped to Scheme. */
702 if (handle
!= SCM_BOOL_F
&& !pstate
->revealed
)
705 SCM_SETCDR (handle
, SCM_CDR (print_state_pool
));
706 SCM_SETCDR (print_state_pool
, handle
);
716 scm_intprint (n
, radix
, port
)
721 char num_buf
[SCM_INTBUFLEN
];
722 scm_lfwrite (num_buf
, scm_iint2str (n
, radix
, num_buf
), port
);
725 /* Print an object of unrecognized type.
729 scm_ipruk (hdr
, ptr
, port
)
734 scm_puts ("#<unknown-", port
);
735 scm_puts (hdr
, port
);
738 scm_puts (" (0x", port
);
739 scm_intprint (SCM_CAR (ptr
), 16, port
);
740 scm_puts (" . 0x", port
);
741 scm_intprint (SCM_CDR (ptr
), 16, port
);
742 scm_puts (") @", port
);
744 scm_puts (" 0x", port
);
745 scm_intprint (ptr
, 16, port
);
746 scm_putc ('>', port
);
754 scm_iprlist (hdr
, exp
, tlr
, port
, pstate
)
759 scm_print_state
*pstate
;
761 register SCM hare
, tortoise
;
762 int floor
= pstate
->top
- 2;
763 scm_puts (hdr
, port
);
768 /* Run a hare and tortoise so that total time complexity will be
769 O(depth * N) instead of O(N^2). */
770 hare
= SCM_CDR (exp
);
772 while (SCM_NIMP (hare
) && SCM_ECONSP (hare
))
774 if (hare
== tortoise
)
776 hare
= SCM_CDR (hare
);
777 if (SCM_IMP (hare
) || SCM_NECONSP (hare
))
779 hare
= SCM_CDR (hare
);
780 tortoise
= SCM_CDR (tortoise
);
783 /* No cdr cycles intrinsic to this list */
784 scm_iprin1 (SCM_CAR (exp
), port
, pstate
);
786 for (; SCM_NIMP (exp
); exp
= SCM_CDR (exp
))
790 if (SCM_NECONSP (exp
))
792 for (i
= floor
; i
>= 0; --i
)
793 if (pstate
->ref_stack
[i
] == exp
)
795 PUSH_REF (pstate
, exp
);
796 scm_putc (' ', port
);
798 scm_iprin1 (SCM_CAR (exp
), port
, pstate
);
800 if (SCM_NNULLP (exp
))
802 scm_puts (" . ", port
);
803 scm_iprin1 (exp
, port
, pstate
);
807 scm_putc (tlr
, port
);
808 pstate
->top
= floor
+ 2;
813 int n
= pstate
->length
;
815 scm_iprin1 (SCM_CAR (exp
), port
, pstate
);
816 exp
= SCM_CDR (exp
); --n
;
817 for (; SCM_NIMP (exp
); exp
= SCM_CDR (exp
))
819 register unsigned long i
;
821 if (SCM_NECONSP (exp
))
823 for (i
= 0; i
< pstate
->top
; ++i
)
824 if (pstate
->ref_stack
[i
] == exp
)
830 scm_puts (" ...", port
);
836 PUSH_REF(pstate
, exp
);
837 ++pstate
->list_offset
;
838 scm_putc (' ', port
);
840 scm_iprin1 (SCM_CAR (exp
), port
, pstate
);
843 if (SCM_NNULLP (exp
))
845 scm_puts (" . ", port
);
846 scm_iprin1 (exp
, port
, pstate
);
849 pstate
->list_offset
-= pstate
->top
- floor
- 2;
853 pstate
->list_offset
-= pstate
->top
- floor
- 2;
856 scm_puts (" . ", port
);
857 print_circref (port
, pstate
, exp
);
864 scm_valid_oport_value_p (SCM val
)
866 return (SCM_NIMP (val
)
867 && (SCM_OPOUTPORTP (val
)
869 && SCM_NIMP (SCM_CAR (val
))
870 && SCM_OPOUTPORTP (SCM_CAR (val
))
871 && SCM_NIMP (SCM_CDR (val
))
872 && SCM_PRINT_STATE_P (SCM_CDR (val
)))));
875 SCM_PROC(s_write
, "write", 1, 1, 0, scm_write
);
878 scm_write (obj
, port
)
882 if (SCM_UNBNDP (port
))
885 SCM_ASSERT (scm_valid_oport_value_p (port
), port
, SCM_ARG2
, s_write
);
887 scm_prin1 (obj
, port
, 1);
891 scm_close_port (port
);
894 return SCM_UNSPECIFIED
;
898 SCM_PROC(s_display
, "display", 1, 1, 0, scm_display
);
901 scm_display (obj
, port
)
905 if (SCM_UNBNDP (port
))
908 SCM_ASSERT (scm_valid_oport_value_p (port
), port
, SCM_ARG2
, s_display
);
910 scm_prin1 (obj
, port
, 0);
914 scm_close_port (port
);
917 return SCM_UNSPECIFIED
;
920 SCM_PROC(s_newline
, "newline", 0, 1, 0, scm_newline
);
926 if (SCM_UNBNDP (port
))
929 SCM_ASSERT (scm_valid_oport_value_p (port
), port
, SCM_ARG1
, s_newline
);
931 scm_putc ('\n', SCM_COERCE_OUTPORT (port
));
935 scm_close_port (port
);
939 if (port
== scm_cur_outp
)
941 return SCM_UNSPECIFIED
;
944 SCM_PROC(s_write_char
, "write-char", 1, 1, 0, scm_write_char
);
947 scm_write_char (chr
, port
)
951 if (SCM_UNBNDP (port
))
954 SCM_ASSERT (scm_valid_oport_value_p (port
), port
, SCM_ARG2
, s_write_char
);
956 SCM_ASSERT (SCM_ICHRP (chr
), chr
, SCM_ARG1
, s_write_char
);
957 scm_putc ((int) SCM_ICHR (chr
), SCM_COERCE_OUTPORT (port
));
961 scm_close_port (port
);
964 return SCM_UNSPECIFIED
;
969 /* Call back to Scheme code to do the printing of special objects
970 (like structs). SCM_PRINTER_APPLY applies PROC to EXP and a pair
971 containing PORT and PSTATE. This pair can be used as the port for
972 display/write etc to continue the current print chain. The REVEALED
973 field of PSTATE is set to true to indicate that the print state has
974 escaped to Scheme and thus has to be freed by the GC. */
977 scm_printer_apply (proc
, exp
, port
, pstate
)
979 scm_print_state
*pstate
;
981 SCM pair
= scm_cons (port
, pstate
->handle
);
982 pstate
->revealed
= 1;
983 return scm_apply (proc
, exp
, scm_cons (pair
, scm_listofnull
));
991 SCM vtable
, layout
, printer
, type
;
993 scm_init_opts (scm_print_options
, scm_print_opts
, SCM_N_PRINT_OPTIONS
);
994 vtable
= scm_make_vtable_vtable (scm_make_struct_layout (scm_nullstr
),
997 layout
= scm_make_struct_layout (scm_makfrom0str (SCM_PRINT_STATE_LAYOUT
));
998 printer
= scm_make_subr_opt (s_print_state_printer
,
1000 (SCM (*) ()) print_state_printer
,
1001 0 /* Don't bind the name. */);
1002 type
= scm_make_struct (vtable
, SCM_INUM0
, SCM_LIST2 (layout
, printer
));
1003 print_state_pool
= scm_permanent_object (scm_cons (type
, SCM_EOL
));
1005 scm_print_state_vtable
= type
;