* syncase.scm (psyncomp): New procedure: Recompiles psyntax.pp.
[bpt/guile.git] / libguile / print.c
CommitLineData
1e598865 1/* Copyright (C) 1995,1996,1997 Free Software Foundation, Inc.
0f2d19dd
JB
2 *
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)
6 * any later version.
7 *
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.
12 *
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
82892bed
JB
15 * the Free Software Foundation, Inc., 59 Temple Place, Suite 330,
16 * Boston, MA 02111-1307 USA
0f2d19dd
JB
17 *
18 * As a special exception, the Free Software Foundation gives permission
19 * for additional uses of the text contained in its release of GUILE.
20 *
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.
26 *
27 * This exception does not however invalidate any other reasons why
28 * the executable file might be covered by the GNU General Public License.
29 *
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.
37 *
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.
82892bed 40 * If you do not wish that, delete this exception notice. */
0f2d19dd
JB
41\f
42
43#include <stdio.h>
44#include "_scm.h"
20e6290e
JB
45#include "chars.h"
46#include "genio.h"
47#include "mbstrings.h"
48#include "smob.h"
49#include "eval.h"
50#include "procprop.h"
51#include "read.h"
52#include "weaks.h"
53#include "unif.h"
dbef8851 54#include "alist.h"
c62fbfe1 55#include "struct.h"
c4f37e80 56#include "fluids.h"
0f2d19dd 57
20e6290e 58#include "print.h"
0f2d19dd
JB
59\f
60
61/* {Names of immediate symbols}
62 *
63 * This table must agree with the declarations in scm.h: {Immediate Symbols}.
64 */
65
66char *scm_isymnames[] =
67{
68 /* This table must agree with the declarations */
69 "#@and",
70 "#@begin",
71 "#@case",
72 "#@cond",
73 "#@do",
74 "#@if",
75 "#@lambda",
76 "#@let",
77 "#@let*",
78 "#@letrec",
79 "#@or",
80 "#@quote",
81 "#@set!",
82 "#@define",
83#if 0
84 "#@literal-variable-ref",
85 "#@literal-variable-set!",
86#endif
87 "#@apply",
88 "#@call-with-current-continuation",
89
90 /* user visible ISYMS */
91 /* other keywords */
92 /* Flags */
93
94 "#f",
95 "#t",
96 "#<undefined>",
97 "#<eof>",
98 "()",
99 "#<unspecified>"
100};
101
e6e4c9af 102scm_option scm_print_opts[] = {
b7ff98dd 103 { SCM_OPTION_SCM, "closure-hook", SCM_BOOL_F,
84f6a34a
MD
104 "Hook for printing closures." },
105 { SCM_OPTION_BOOLEAN, "source", 0,
106 "Print closures with source." }
e6e4c9af
MD
107};
108
b7ff98dd 109SCM_PROC (s_print_options, "print-options-interface", 0, 1, 0, scm_print_options);
1cc91f1b 110
e6e4c9af 111SCM
a51ea417
MD
112scm_print_options (setting)
113 SCM setting;
e6e4c9af 114{
a51ea417 115 SCM ans = scm_options (setting,
b7ff98dd
MD
116 scm_print_opts,
117 SCM_N_PRINT_OPTIONS,
118 s_print_options);
e6e4c9af
MD
119 return ans;
120}
e6e4c9af 121
0f2d19dd
JB
122\f
123/* {Printing of Scheme Objects}
124 */
125
a51ea417 126/* Detection of circular references.
c62fbfe1
MD
127 *
128 * Due to other constraints in the implementation, this code has bad
129 * time complexity (O (depth * N)), The printer code will be
130 * completely rewritten before next release of Guile. The new code
131 * will be O(N).
a51ea417 132 */
c62fbfe1 133#define PUSH_REF(pstate, obj) \
a51ea417 134{ \
c62fbfe1
MD
135 pstate->ref_stack[pstate->top++] = (obj); \
136 if (pstate->top == pstate->ceiling) \
137 grow_ref_stack (pstate); \
138}
a51ea417 139
c62fbfe1 140#define ENTER_NESTED_DATA(pstate, obj, label) \
a51ea417 141{ \
c62fbfe1
MD
142 register int i; \
143 for (i = 0; i < pstate->top; ++i) \
144 if (pstate->ref_stack[i] == (obj)) \
145 goto label; \
146 if (pstate->fancyp) \
147 { \
148 if (pstate->top - pstate->list_offset >= pstate->level) \
149 { \
150 scm_gen_putc ('#', port); \
151 return; \
152 } \
153 } \
154 PUSH_REF(pstate, obj); \
a51ea417
MD
155} \
156
c62fbfe1
MD
157#define EXIT_NESTED_DATA(pstate) { --pstate->top; }
158
159static SCM print_state_pool;
160
c4f37e80
MV
161/* This fluid is an implicit parameter to scm_iprin (and thus
162scm_display and scm_write) and carries the current print_state when
163Scheme code is called to do some printing. That way, circular
164references are detected even when they reach across calls to `display'
165or `write'.
166
167The fluid is not visible to Scheme code, but maybe it should. */
168
169static SCM print_state_fluid;
170static int print_state_fluid_num;
171
f843a84c 172#ifdef GUILE_DEBUG /* Used for debugging purposes */
c62fbfe1 173SCM_PROC(s_current_pstate, "current-pstate", 0, 0, 0, scm_current_pstate);
1cc91f1b 174
c62fbfe1
MD
175SCM
176scm_current_pstate ()
c62fbfe1
MD
177{
178 return SCM_CADR (print_state_pool);
179}
180#endif
181
182#define PSTATE_SIZE 50L
183
698c0295
MD
184static SCM make_print_state SCM_P ((void));
185
186static SCM
187make_print_state ()
188{
189 SCM print_state = scm_make_struct (SCM_CAR (print_state_pool), /* pstate type */
bf685b6d 190 SCM_INUM0,
698c0295 191 SCM_EOL);
bf685b6d
MD
192 scm_print_state *pstate = SCM_PRINT_STATE (print_state);
193 pstate->ref_vect = scm_make_vector (SCM_MAKINUM (PSTATE_SIZE),
194 SCM_UNDEFINED,
195 SCM_UNDEFINED);
196 pstate->ref_stack = SCM_VELTS (pstate->ref_vect);
197 pstate->ceiling = SCM_LENGTH (pstate->ref_vect);
698c0295
MD
198 return print_state;
199}
1cc91f1b 200
c62fbfe1
MD
201SCM
202scm_make_print_state ()
c62fbfe1 203{
698c0295
MD
204 SCM answer = 0;
205
206 /* First try to allocate a print state from the pool */
207 SCM_DEFER_INTS;
208 if (SCM_NNULLP (SCM_CDR (print_state_pool)))
209 {
210 answer = SCM_CADR (print_state_pool);
211 SCM_SETCDR (print_state_pool, SCM_CDDR (print_state_pool));
212 }
213 SCM_ALLOW_INTS;
214
215 return answer ? answer : make_print_state ();
c62fbfe1 216}
a51ea417 217
698c0295
MD
218void
219scm_free_print_state (print_state)
220 SCM print_state;
221{
222 SCM handle;
223 scm_print_state *pstate = SCM_PRINT_STATE (print_state);
224 /* Cleanup before returning print state to pool.
225 * It is better to do it here. Doing it in scm_prin1
226 * would cost more since that function is called much more
227 * often.
228 */
229 pstate->fancyp = 0;
230 SCM_NEWCELL (handle);
231 SCM_DEFER_INTS;
232 SCM_SETCAR (handle, print_state);
233 SCM_SETCDR (handle, SCM_CDR (print_state_pool));
234 SCM_SETCDR (print_state_pool, handle);
235 SCM_ALLOW_INTS;
236}
1cc91f1b
JB
237
238static void grow_ref_stack SCM_P ((scm_print_state *pstate));
239
a51ea417 240static void
c62fbfe1
MD
241grow_ref_stack (pstate)
242 scm_print_state *pstate;
a51ea417 243{
bf685b6d
MD
244 int new_size = 2 * pstate->ceiling;
245 scm_vector_set_length_x (pstate->ref_vect, SCM_MAKINUM (new_size));
246 pstate->ref_stack = SCM_VELTS (pstate->ref_vect);
247 pstate->ceiling = new_size;
a51ea417
MD
248}
249
1cc91f1b
JB
250
251static void print_circref SCM_P ((SCM port, scm_print_state *pstate, SCM ref));
252
a51ea417 253static void
c62fbfe1
MD
254print_circref (port, pstate, ref)
255 SCM port;
256 scm_print_state *pstate;
257 SCM ref;
a51ea417 258{
c62fbfe1
MD
259 register int i;
260 int self = pstate->top - 1;
261 i = pstate->top - 1;
262 if (SCM_CONSP (pstate->ref_stack[i]))
263 {
264 while (i > 0)
265 {
266 if (SCM_NCONSP (pstate->ref_stack[i - 1])
267 || SCM_CDR (pstate->ref_stack[i - 1]) != pstate->ref_stack[i])
268 break;
269 --i;
270 }
271 self = i;
272 }
273 for (i = pstate->top - 1; 1; --i)
274 if (pstate->ref_stack[i] == ref)
275 break;
276 scm_gen_putc ('#', port);
277 scm_intprint (i - self, 10, port);
278 scm_gen_putc ('#', port);
a51ea417
MD
279}
280
c62fbfe1 281/* Print generally. Handles both write and display according to PSTATE.
0f2d19dd 282 */
a51ea417 283
1cc91f1b 284
0f2d19dd 285void
c62fbfe1 286scm_iprin1 (exp, port, pstate)
0f2d19dd
JB
287 SCM exp;
288 SCM port;
c62fbfe1 289 scm_print_state *pstate;
0f2d19dd
JB
290{
291 register long i;
292taloop:
293 switch (7 & (int) exp)
294 {
295 case 2:
296 case 6:
297 scm_intprint (SCM_INUM (exp), 10, port);
298 break;
299 case 4:
300 if (SCM_ICHRP (exp))
301 {
302 i = SCM_ICHR (exp);
c62fbfe1 303 scm_put_wchar (i, port, SCM_WRITINGP (pstate));
0f2d19dd
JB
304
305 }
a51ea417 306 else if (SCM_IFLAGP (exp)
0f2d19dd 307 && (SCM_ISYMNUM (exp) < (sizeof scm_isymnames / sizeof (char *))))
08b5b88c 308 scm_gen_puts (scm_regular_string, SCM_ISYMCHARS (exp), port);
0f2d19dd
JB
309 else if (SCM_ILOCP (exp))
310 {
311 scm_gen_puts (scm_regular_string, "#@", port);
312 scm_intprint ((long) SCM_IFRAME (exp), 10, port);
313 scm_gen_putc (SCM_ICDRP (exp) ? '-' : '+', port);
314 scm_intprint ((long) SCM_IDIST (exp), 10, port);
315 }
316 else
317 goto idef;
318 break;
319 case 1:
320 /* gloc */
321 scm_gen_puts (scm_regular_string, "#@", port);
322 exp = SCM_CAR (exp - 1);
323 goto taloop;
324 default:
325 idef:
326 scm_ipruk ("immediate", exp, port);
327 break;
328 case 0:
329 switch (SCM_TYP7 (exp))
330 {
331 case scm_tcs_cons_gloc:
332
333 if (SCM_CDR (SCM_CAR (exp) - 1L) == 0)
334 {
c4f37e80 335 ENTER_NESTED_DATA (pstate, exp, circref);
bafcafb2 336 scm_print_struct (exp, port, pstate);
c4f37e80 337 EXIT_NESTED_DATA (pstate);
0f2d19dd
JB
338 break;
339 }
340
341 case scm_tcs_cons_imcar:
342 case scm_tcs_cons_nimcar:
c62fbfe1
MD
343 ENTER_NESTED_DATA (pstate, exp, circref);
344 scm_iprlist ("(", exp, ')', port, pstate);
345 EXIT_NESTED_DATA (pstate);
a51ea417
MD
346 break;
347 circref:
c62fbfe1 348 print_circref (port, pstate, exp);
0f2d19dd 349 break;
7332df66
MD
350 macros:
351 if (SCM_FALSEP (scm_closure_p (SCM_CDR (exp))))
352 goto prinmacro;
0f2d19dd 353 case scm_tcs_closures:
7332df66
MD
354 /* The user supplied print closure procedure must handle
355 macro closures as well. */
a51ea417
MD
356 if (SCM_NFALSEP (scm_procedure_p (SCM_PRINT_CLOSURE)))
357 {
358 SCM ans = scm_cons2 (exp, port,
c62fbfe1
MD
359 scm_cons (SCM_WRITINGP (pstate)
360 ? SCM_BOOL_T
361 : SCM_BOOL_F,
362 SCM_EOL));
a51ea417 363 ans = scm_apply (SCM_PRINT_CLOSURE, ans, SCM_EOL);
a51ea417 364 }
84f6a34a 365 else
0f2d19dd 366 {
84f6a34a 367 SCM name, code;
7332df66
MD
368 if (SCM_TYP16 (exp) == scm_tc16_macro)
369 {
370 /* Printing a macro. */
371 prinmacro:
372 name = scm_procedure_name (SCM_CDR (exp));
373 if (SCM_FALSEP (scm_closure_p (SCM_CDR (exp))))
374 {
375 code = 0;
376 scm_gen_puts (scm_regular_string, "#<primitive-",
377 port);
378 }
379 else
380 {
381 code = SCM_CODE (SCM_CDR (exp));
382 scm_gen_puts (scm_regular_string, "#<", port);
383 }
384 if (SCM_CAR (exp) & (3L << 16))
385 scm_gen_puts (scm_regular_string, "macro", port);
386 else
387 scm_gen_puts (scm_regular_string, "syntax", port);
388 if (SCM_CAR (exp) & (2L << 16))
389 scm_gen_putc ('!', port);
390 }
391 else
392 {
393 /* Printing a closure. */
394 name = scm_procedure_name (exp);
395 code = SCM_CODE (exp);
396 scm_gen_puts (scm_regular_string, "#<procedure",
397 port);
398 }
84f6a34a 399 if (SCM_NIMP (name) && SCM_ROSTRINGP (name))
0f2d19dd 400 {
7332df66 401 scm_gen_putc (' ', port);
84f6a34a 402 scm_gen_puts (scm_regular_string, SCM_ROCHARS (name), port);
7332df66
MD
403 }
404 if (code)
405 {
0f2d19dd 406 scm_gen_putc (' ', port);
7332df66 407 scm_iprin1 (SCM_CAR (code), port, pstate);
0f2d19dd 408 }
7332df66 409 if (code && SCM_PRINT_SOURCE_P)
84f6a34a
MD
410 {
411 code = scm_unmemocopy (SCM_CDR (code),
412 SCM_EXTEND_ENV (SCM_CAR (code),
413 SCM_EOL,
414 SCM_ENV (exp)));
c62fbfe1
MD
415 ENTER_NESTED_DATA (pstate, exp, circref);
416 scm_iprlist (" ", code, '>', port, pstate);
417 EXIT_NESTED_DATA (pstate);
84f6a34a
MD
418 }
419 else
420 scm_gen_putc ('>', port);
0f2d19dd
JB
421 }
422 break;
423 case scm_tc7_mb_string:
424 case scm_tc7_mb_substring:
c62fbfe1 425 scm_print_mb_string (exp, port, SCM_WRITINGP (pstate));
0f2d19dd
JB
426 break;
427 case scm_tc7_substring:
428 case scm_tc7_string:
c62fbfe1 429 if (SCM_WRITINGP (pstate))
0f2d19dd 430 {
dbef8851 431 scm_gen_putc ('"', port);
0f2d19dd
JB
432 for (i = 0; i < SCM_ROLENGTH (exp); ++i)
433 switch (SCM_ROCHARS (exp)[i])
434 {
dbef8851 435 case '"':
0f2d19dd
JB
436 case '\\':
437 scm_gen_putc ('\\', port);
438 default:
439 scm_gen_putc (SCM_ROCHARS (exp)[i], port);
440 }
dbef8851 441 scm_gen_putc ('"', port);
0f2d19dd
JB
442 break;
443 }
444 else
445 scm_gen_write (scm_regular_string, SCM_ROCHARS (exp),
446 (scm_sizet) SCM_ROLENGTH (exp),
447 port);
448 break;
449 case scm_tcs_symbols:
450 if (SCM_MB_STRINGP (exp))
451 {
452 scm_print_mb_symbol (exp, port);
453 break;
454 }
455 else
456 {
457 int pos;
458 int end;
459 int len;
460 char * str;
461 int weird;
462 int maybe_weird;
4dc2435a 463 int mw_pos = 0;
0f2d19dd
JB
464
465 len = SCM_LENGTH (exp);
466 str = SCM_CHARS (exp);
467 scm_remember (&exp);
468 pos = 0;
469 weird = 0;
470 maybe_weird = 0;
471
472 if (len == 0)
473 scm_gen_write (scm_regular_string, "#{}#", 4, port);
474
475 for (end = pos; end < len; ++end)
476 switch (str[end])
477 {
478#ifdef BRACKETS_AS_PARENS
479 case '[':
480 case ']':
481#endif
482 case '(':
483 case ')':
dbef8851 484 case '"':
0f2d19dd
JB
485 case ';':
486 case SCM_WHITE_SPACES:
487 case SCM_LINE_INCREMENTORS:
488 weird_handler:
489 if (maybe_weird)
490 {
491 end = mw_pos;
492 maybe_weird = 0;
493 }
494 if (!weird)
495 {
496 scm_gen_write (scm_regular_string, "#{", 2, port);
497 weird = 1;
498 }
499 if (pos < end)
500 {
501 scm_gen_write (scm_regular_string, str + pos, end - pos, port);
502 }
503 {
504 char buf[2];
505 buf[0] = '\\';
506 buf[1] = str[end];
507 scm_gen_write (scm_regular_string, buf, 2, port);
508 }
509 pos = end + 1;
510 break;
511 case '\\':
512 if (weird)
513 goto weird_handler;
514 if (!maybe_weird)
515 {
516 maybe_weird = 1;
517 mw_pos = pos;
518 }
519 break;
520 case '}':
521 case '#':
522 if (weird)
523 goto weird_handler;
524 break;
525 default:
526 break;
527 }
528 if (pos < end)
529 scm_gen_write (scm_regular_string, str + pos, end - pos, port);
530 if (weird)
531 scm_gen_write (scm_regular_string, "}#", 2, port);
532 break;
533 }
534 case scm_tc7_wvect:
c62fbfe1 535 ENTER_NESTED_DATA (pstate, exp, circref);
0f2d19dd
JB
536 if (SCM_IS_WHVEC (exp))
537 scm_gen_puts (scm_regular_string, "#wh(", port);
538 else
539 scm_gen_puts (scm_regular_string, "#w(", port);
540 goto common_vector_printer;
541
542 case scm_tc7_vector:
c62fbfe1 543 ENTER_NESTED_DATA (pstate, exp, circref);
0f2d19dd
JB
544 scm_gen_puts (scm_regular_string, "#(", port);
545 common_vector_printer:
9fbaf27c
MD
546 {
547 int last = SCM_LENGTH (exp) - 1;
548 int cutp = 0;
549 if (pstate->fancyp && SCM_LENGTH (exp) > pstate->length)
550 {
551 last = pstate->length - 1;
552 cutp = 1;
553 }
554 for (i = 0; i < last; ++i)
555 {
556 /* CHECK_INTS; */
557 scm_iprin1 (SCM_VELTS (exp)[i], port, pstate);
558 scm_gen_putc (' ', port);
559 }
560 if (i == last)
561 {
562 /* CHECK_INTS; */
563 scm_iprin1 (SCM_VELTS (exp)[i], port, pstate);
564 }
565 if (cutp)
566 scm_gen_puts (scm_regular_string, " ...", port);
567 scm_gen_putc (')', port);
568 }
c62fbfe1 569 EXIT_NESTED_DATA (pstate);
0f2d19dd
JB
570 break;
571 case scm_tc7_bvect:
572 case scm_tc7_byvect:
573 case scm_tc7_svect:
574 case scm_tc7_ivect:
575 case scm_tc7_uvect:
576 case scm_tc7_fvect:
577 case scm_tc7_dvect:
578 case scm_tc7_cvect:
579#ifdef LONGLONGS
580 case scm_tc7_llvect:
581#endif
c62fbfe1 582 scm_raprin1 (exp, port, pstate);
0f2d19dd
JB
583 break;
584 case scm_tcs_subrs:
585 scm_gen_puts (scm_regular_string, "#<primitive-procedure ", port);
586 scm_gen_puts ((SCM_MB_STRINGP (SCM_SNAME(exp))
587 ? scm_mb_string
588 : scm_regular_string),
589 SCM_CHARS (SCM_SNAME (exp)), port);
590 scm_gen_putc ('>', port);
591 break;
592#ifdef CCLO
593 case scm_tc7_cclo:
594 scm_gen_puts (scm_regular_string, "#<compiled-closure ", port);
c62fbfe1 595 scm_iprin1 (SCM_CCLO_SUBR (exp), port, pstate);
0f2d19dd
JB
596 scm_gen_putc ('>', port);
597 break;
598#endif
599 case scm_tc7_contin:
600 scm_gen_puts (scm_regular_string, "#<continuation ", port);
601 scm_intprint (SCM_LENGTH (exp), 10, port);
602 scm_gen_puts (scm_regular_string, " @ ", port);
603 scm_intprint ((long) SCM_CHARS (exp), 16, port);
604 scm_gen_putc ('>', port);
605 break;
606 case scm_tc7_port:
607 i = SCM_PTOBNUM (exp);
c62fbfe1
MD
608 if (i < scm_numptob
609 && scm_ptobs[i].print
610 && (scm_ptobs[i].print) (exp, port, pstate))
0f2d19dd
JB
611 break;
612 goto punk;
613 case scm_tc7_smob:
c62fbfe1 614 ENTER_NESTED_DATA (pstate, exp, circref);
0f2d19dd
JB
615 i = SCM_SMOBNUM (exp);
616 if (i < scm_numsmob && scm_smobs[i].print
c62fbfe1 617 && (scm_smobs[i].print) (exp, port, pstate))
a51ea417 618 {
c62fbfe1 619 EXIT_NESTED_DATA (pstate);
a51ea417
MD
620 break;
621 }
c62fbfe1 622 EXIT_NESTED_DATA (pstate);
7332df66
MD
623 /* Macros have their print field set to NULL. They are
624 handled at the same place as closures in order to achieve
625 non-redundancy. Placing the condition here won't slow
626 down printing of other smobs. */
627 if (SCM_TYP16 (exp) == scm_tc16_macro)
628 goto macros;
0f2d19dd 629 default:
a51ea417
MD
630 punk:
631 scm_ipruk ("type", exp, port);
0f2d19dd
JB
632 }
633 }
634}
635
c62fbfe1
MD
636/* Print states are necessary for circular reference safe printing.
637 * They are also expensive to allocate. Therefore print states are
638 * kept in a pool so that they can be reused.
639 */
1cc91f1b 640
a51ea417 641void
c62fbfe1 642scm_prin1 (exp, port, writingp)
a51ea417
MD
643 SCM exp;
644 SCM port;
c62fbfe1 645 int writingp;
a51ea417 646{
c4f37e80
MV
647 SCM handle = SCM_BOOL_F; /* Will GC protect the handle whilst unlinked */
648 SCM pstate_scm;
c62fbfe1
MD
649 scm_print_state *pstate;
650
c4f37e80
MV
651 /* If there is currently a print state active, use that. Else
652 create a new one. */
653
654 pstate_scm = SCM_FAST_FLUID_REF (print_state_fluid_num);
655 if (pstate_scm == SCM_BOOL_F)
c62fbfe1 656 {
c4f37e80
MV
657 /* First try to allocate a print state from the pool */
658 SCM_DEFER_INTS;
659 if (SCM_NNULLP (SCM_CDR (print_state_pool)))
660 {
661 handle = SCM_CDR (print_state_pool);
662 SCM_SETCDR (print_state_pool, SCM_CDDR (print_state_pool));
663 }
664 SCM_ALLOW_INTS;
665 if (handle == SCM_BOOL_F)
666 handle = scm_cons (make_print_state (), SCM_EOL);
667 pstate_scm = SCM_CAR (handle);
c62fbfe1 668 }
c62fbfe1 669
c4f37e80 670 pstate = SCM_PRINT_STATE (pstate_scm);
c62fbfe1
MD
671 pstate->writingp = writingp;
672 scm_iprin1 (exp, port, pstate);
673
c4f37e80
MV
674 /* Return print state to pool, if it has been created above. */
675 if (handle != SCM_BOOL_F)
676 {
677 SCM_DEFER_INTS;
678 SCM_SETCDR (handle, SCM_CDR (print_state_pool));
679 SCM_SETCDR (print_state_pool, handle);
680 SCM_ALLOW_INTS;
681 }
a51ea417
MD
682}
683
0f2d19dd
JB
684
685/* Print an integer.
686 */
1cc91f1b 687
0f2d19dd
JB
688void
689scm_intprint (n, radix, port)
690 long n;
691 int radix;
692 SCM port;
0f2d19dd
JB
693{
694 char num_buf[SCM_INTBUFLEN];
695 scm_gen_write (scm_regular_string, num_buf, scm_iint2str (n, radix, num_buf), port);
696}
697
698/* Print an object of unrecognized type.
699 */
1cc91f1b 700
0f2d19dd
JB
701void
702scm_ipruk (hdr, ptr, port)
703 char *hdr;
704 SCM ptr;
705 SCM port;
0f2d19dd
JB
706{
707 scm_gen_puts (scm_regular_string, "#<unknown-", port);
708 scm_gen_puts (scm_regular_string, hdr, port);
709 if (SCM_CELLP (ptr))
710 {
711 scm_gen_puts (scm_regular_string, " (0x", port);
712 scm_intprint (SCM_CAR (ptr), 16, port);
713 scm_gen_puts (scm_regular_string, " . 0x", port);
714 scm_intprint (SCM_CDR (ptr), 16, port);
715 scm_gen_puts (scm_regular_string, ") @", port);
716 }
717 scm_gen_puts (scm_regular_string, " 0x", port);
718 scm_intprint (ptr, 16, port);
719 scm_gen_putc ('>', port);
720}
721
722/* Print a list.
723 */
a51ea417 724
1cc91f1b 725
0f2d19dd 726void
c62fbfe1 727scm_iprlist (hdr, exp, tlr, port, pstate)
0f2d19dd
JB
728 char *hdr;
729 SCM exp;
805df3e8 730 int tlr;
0f2d19dd 731 SCM port;
c62fbfe1 732 scm_print_state *pstate;
0f2d19dd 733{
c62fbfe1
MD
734 register int i;
735 register SCM hare, tortoise;
736 int floor = pstate->top - 2;
0f2d19dd
JB
737 scm_gen_puts (scm_regular_string, hdr, port);
738 /* CHECK_INTS; */
c62fbfe1
MD
739 if (pstate->fancyp)
740 goto fancy_printing;
741
742 /* Run a hare and tortoise so that total time complexity will be
743 O(depth * N) instead of O(N^2). */
744 hare = SCM_CDR (exp);
745 tortoise = exp;
2fab3faa 746 while (SCM_NIMP (hare) && SCM_ECONSP (hare))
c62fbfe1
MD
747 {
748 if (hare == tortoise)
749 goto fancy_printing;
750 hare = SCM_CDR (hare);
2fab3faa 751 if (SCM_IMP (hare) || SCM_NECONSP (hare))
c62fbfe1
MD
752 break;
753 hare = SCM_CDR (hare);
754 tortoise = SCM_CDR (tortoise);
755 }
756
757 /* No cdr cycles intrinsic to this list */
758 scm_iprin1 (SCM_CAR (exp), port, pstate);
0f2d19dd
JB
759 exp = SCM_CDR (exp);
760 for (; SCM_NIMP (exp); exp = SCM_CDR (exp))
761 {
762 if (SCM_NECONSP (exp))
763 break;
c62fbfe1
MD
764 for (i = floor; i >= 0; --i)
765 if (pstate->ref_stack[i] == exp)
766 goto circref;
767 PUSH_REF (pstate, exp);
0f2d19dd
JB
768 scm_gen_putc (' ', port);
769 /* CHECK_INTS; */
c62fbfe1 770 scm_iprin1 (SCM_CAR (exp), port, pstate);
0f2d19dd
JB
771 }
772 if (SCM_NNULLP (exp))
773 {
774 scm_gen_puts (scm_regular_string, " . ", port);
c62fbfe1 775 scm_iprin1 (exp, port, pstate);
0f2d19dd 776 }
c62fbfe1 777
a51ea417 778end:
0f2d19dd 779 scm_gen_putc (tlr, port);
c62fbfe1 780 pstate->top = floor + 2;
a51ea417 781 return;
c62fbfe1
MD
782
783fancy_printing:
784 {
785 int n = pstate->length;
786
787 scm_iprin1 (SCM_CAR (exp), port, pstate);
788 exp = SCM_CDR (exp); --n;
789 for (; SCM_NIMP (exp); exp = SCM_CDR (exp))
790 {
791 if (SCM_NECONSP (exp))
792 break;
793 for (i = 0; i < pstate->top; ++i)
794 if (pstate->ref_stack[i] == exp)
795 goto fancy_circref;
796 if (pstate->fancyp)
797 {
798 if (n == 0)
799 {
800 scm_gen_puts (scm_regular_string, " ...", port);
801 goto skip_tail;
802 }
803 else
804 --n;
805 }
806 PUSH_REF(pstate, exp);
807 ++pstate->list_offset;
808 scm_gen_putc (' ', port);
809 /* CHECK_INTS; */
810 scm_iprin1 (SCM_CAR (exp), port, pstate);
811 }
812 }
813 if (SCM_NNULLP (exp))
814 {
815 scm_gen_puts (scm_regular_string, " . ", port);
816 scm_iprin1 (exp, port, pstate);
817 }
818skip_tail:
819 pstate->list_offset -= pstate->top - floor - 2;
a51ea417 820 goto end;
a51ea417 821
c62fbfe1
MD
822fancy_circref:
823 pstate->list_offset -= pstate->top - floor - 2;
824
825circref:
826 scm_gen_puts (scm_regular_string, " . ", port);
827 print_circref (port, pstate, exp);
828 goto end;
0f2d19dd
JB
829}
830
831\f
832
833SCM_PROC(s_write, "write", 1, 1, 0, scm_write);
1cc91f1b 834
0f2d19dd
JB
835SCM
836scm_write (obj, port)
837 SCM obj;
838 SCM port;
0f2d19dd
JB
839{
840 if (SCM_UNBNDP (port))
841 port = scm_cur_outp;
842 else
843 SCM_ASSERT (SCM_NIMP (port) && SCM_OPOUTPORTP (port), port, SCM_ARG2, s_write);
a51ea417 844 scm_prin1 (obj, port, 1);
0f2d19dd
JB
845#ifdef HAVE_PIPE
846# ifdef EPIPE
847 if (EPIPE == errno)
848 scm_close_port (port);
849# endif
850#endif
851 return SCM_UNSPECIFIED;
852}
853
854
855SCM_PROC(s_display, "display", 1, 1, 0, scm_display);
1cc91f1b 856
0f2d19dd
JB
857SCM
858scm_display (obj, port)
859 SCM obj;
860 SCM port;
0f2d19dd
JB
861{
862 if (SCM_UNBNDP (port))
863 port = scm_cur_outp;
864 else
865 SCM_ASSERT (SCM_NIMP (port) && SCM_OPOUTPORTP (port), port, SCM_ARG2, s_display);
a51ea417 866 scm_prin1 (obj, port, 0);
0f2d19dd
JB
867#ifdef HAVE_PIPE
868# ifdef EPIPE
869 if (EPIPE == errno)
870 scm_close_port (port);
871# endif
872#endif
873 return SCM_UNSPECIFIED;
874}
875
876SCM_PROC(s_newline, "newline", 0, 1, 0, scm_newline);
1cc91f1b 877
0f2d19dd
JB
878SCM
879scm_newline (port)
880 SCM port;
0f2d19dd
JB
881{
882 if (SCM_UNBNDP (port))
883 port = scm_cur_outp;
884 else
885 SCM_ASSERT (SCM_NIMP (port) && SCM_OPOUTPORTP (port), port, SCM_ARG1, s_newline);
886 scm_gen_putc ('\n', port);
887#ifdef HAVE_PIPE
888# ifdef EPIPE
889 if (EPIPE == errno)
890 scm_close_port (port);
891 else
892# endif
893#endif
894 if (port == scm_cur_outp)
895 scm_fflush (port);
896 return SCM_UNSPECIFIED;
897}
898
899SCM_PROC(s_write_char, "write-char", 1, 1, 0, scm_write_char);
1cc91f1b 900
0f2d19dd
JB
901SCM
902scm_write_char (chr, port)
903 SCM chr;
904 SCM port;
0f2d19dd
JB
905{
906 if (SCM_UNBNDP (port))
907 port = scm_cur_outp;
908 else
909 SCM_ASSERT (SCM_NIMP (port) && SCM_OPOUTPORTP (port), port, SCM_ARG2, s_write_char);
910 SCM_ASSERT (SCM_ICHRP (chr), chr, SCM_ARG1, s_write_char);
911 scm_gen_putc ((int) SCM_ICHR (chr), port);
912#ifdef HAVE_PIPE
913# ifdef EPIPE
914 if (EPIPE == errno)
915 scm_close_port (port);
916# endif
917#endif
918 return SCM_UNSPECIFIED;
919}
920
0f2d19dd
JB
921\f
922
c4f37e80
MV
923/* Routines for calling back to Scheme code to do the printing of
924special objects (like structs). SCM_PRINTER_APPLY applies PROC to EXP
925and PORT while the print_state_fluid is set to PSTATE. When PROC
926inturn calls `display' or `write', this print_state is picked up and
927used to control the printing. */
928
929struct apply_data {
930 SCM proc;
931 SCM arg1;
932 SCM args;
933};
934
935static SCM
936apply_stub (void *data)
937{
938 struct apply_data *cl = (struct apply_data *)data;
939 return scm_apply (cl->proc, cl->arg1, cl->args);
940}
941
942SCM
943scm_printer_apply (proc, exp, port, pstate)
944 SCM proc, exp, port;
945 scm_print_state *pstate;
946{
947 struct apply_data cl;
948 cl.proc = proc;
949 cl.arg1 = exp;
950 cl.args = scm_cons (port, scm_listofnull);
951 return scm_internal_with_fluids (scm_cons (print_state_fluid, SCM_EOL),
952 scm_cons (pstate->handle, SCM_EOL),
953 apply_stub, (void *)&cl);
954}
955
956\f
1cc91f1b 957
0f2d19dd
JB
958void
959scm_init_print ()
0f2d19dd 960{
c62fbfe1 961 SCM vtable, type;
c4f37e80 962
b7ff98dd 963 scm_init_opts (scm_print_options, scm_print_opts, SCM_N_PRINT_OPTIONS);
2dfc85c0 964 vtable = scm_make_vtable_vtable (scm_make_struct_layout (scm_nullstr), SCM_INUM0, SCM_EOL);
c62fbfe1
MD
965 type = scm_make_struct (vtable,
966 SCM_INUM0,
967 scm_cons (scm_make_struct_layout (scm_makfrom0str (SCM_PRINT_STATE_LAYOUT)),
968 SCM_EOL));
969 print_state_pool = scm_permanent_object (scm_cons (type, SCM_EOL));
c4f37e80
MV
970
971 print_state_fluid = scm_permanent_object (scm_make_fluid ());
972 scm_fluid_set_x (print_state_fluid, SCM_BOOL_F);
973 print_state_fluid_num = SCM_FLUID_NUM (print_state_fluid);
974
0f2d19dd
JB
975#include "print.x"
976}