*** empty log message ***
[bpt/guile.git] / libguile / print.c
CommitLineData
0f2d19dd
JB
1/* Copyright (C) 1995,1996 Free Software Foundation, Inc.
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
15 * the Free Software Foundation, 675 Mass Ave, Cambridge, MA 02139, USA.
16 *
17 * As a special exception, the Free Software Foundation gives permission
18 * for additional uses of the text contained in its release of GUILE.
19 *
20 * The exception is that, if you link the GUILE library with other files
21 * to produce an executable, this does not by itself cause the
22 * resulting executable to be covered by the GNU General Public License.
23 * Your use of that executable is in no way restricted on account of
24 * linking the GUILE library code into it.
25 *
26 * This exception does not however invalidate any other reasons why
27 * the executable file might be covered by the GNU General Public License.
28 *
29 * This exception applies only to the code released by the
30 * Free Software Foundation under the name GUILE. If you copy
31 * code from other Free Software Foundation releases into a copy of
32 * GUILE, as the General Public License permits, the exception does
33 * not apply to the code that you add in this way. To avoid misleading
34 * anyone as to the status of such modified files, you must delete
35 * this exception notice from them.
36 *
37 * If you write modifications of your own for GUILE, it is your choice
38 * whether to permit this exception to apply to your modifications.
39 * If you do not wish that, delete this exception notice.
40 */
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"
0f2d19dd 56
20e6290e 57#include "print.h"
0f2d19dd
JB
58\f
59
60/* {Names of immediate symbols}
61 *
62 * This table must agree with the declarations in scm.h: {Immediate Symbols}.
63 */
64
65char *scm_isymnames[] =
66{
67 /* This table must agree with the declarations */
68 "#@and",
69 "#@begin",
70 "#@case",
71 "#@cond",
72 "#@do",
73 "#@if",
74 "#@lambda",
75 "#@let",
76 "#@let*",
77 "#@letrec",
78 "#@or",
79 "#@quote",
80 "#@set!",
81 "#@define",
82#if 0
83 "#@literal-variable-ref",
84 "#@literal-variable-set!",
85#endif
86 "#@apply",
87 "#@call-with-current-continuation",
88
89 /* user visible ISYMS */
90 /* other keywords */
91 /* Flags */
92
93 "#f",
94 "#t",
95 "#<undefined>",
96 "#<eof>",
97 "()",
98 "#<unspecified>"
99};
100
e6e4c9af 101scm_option scm_print_opts[] = {
b7ff98dd 102 { SCM_OPTION_SCM, "closure-hook", SCM_BOOL_F,
84f6a34a
MD
103 "Hook for printing closures." },
104 { SCM_OPTION_BOOLEAN, "source", 0,
105 "Print closures with source." }
e6e4c9af
MD
106};
107
b7ff98dd 108SCM_PROC (s_print_options, "print-options-interface", 0, 1, 0, scm_print_options);
e6e4c9af
MD
109#ifdef __STDC__
110SCM
a51ea417 111scm_print_options (SCM setting)
e6e4c9af
MD
112#else
113SCM
a51ea417
MD
114scm_print_options (setting)
115 SCM setting;
e6e4c9af
MD
116#endif
117{
a51ea417 118 SCM ans = scm_options (setting,
b7ff98dd
MD
119 scm_print_opts,
120 SCM_N_PRINT_OPTIONS,
121 s_print_options);
e6e4c9af
MD
122 return ans;
123}
e6e4c9af 124
0f2d19dd
JB
125\f
126/* {Printing of Scheme Objects}
127 */
128
a51ea417 129/* Detection of circular references.
c62fbfe1
MD
130 *
131 * Due to other constraints in the implementation, this code has bad
132 * time complexity (O (depth * N)), The printer code will be
133 * completely rewritten before next release of Guile. The new code
134 * will be O(N).
a51ea417 135 */
c62fbfe1 136#define PUSH_REF(pstate, obj) \
a51ea417 137{ \
c62fbfe1
MD
138 pstate->ref_stack[pstate->top++] = (obj); \
139 if (pstate->top == pstate->ceiling) \
140 grow_ref_stack (pstate); \
141}
a51ea417 142
c62fbfe1 143#define ENTER_NESTED_DATA(pstate, obj, label) \
a51ea417 144{ \
c62fbfe1
MD
145 register int i; \
146 for (i = 0; i < pstate->top; ++i) \
147 if (pstate->ref_stack[i] == (obj)) \
148 goto label; \
149 if (pstate->fancyp) \
150 { \
151 if (pstate->top - pstate->list_offset >= pstate->level) \
152 { \
153 scm_gen_putc ('#', port); \
154 return; \
155 } \
156 } \
157 PUSH_REF(pstate, obj); \
a51ea417
MD
158} \
159
c62fbfe1
MD
160#define EXIT_NESTED_DATA(pstate) { --pstate->top; }
161
162static SCM print_state_pool;
163
164#if 1 /* Used for debugging purposes */
165SCM_PROC(s_current_pstate, "current-pstate", 0, 0, 0, scm_current_pstate);
166#ifdef __STDC__
167SCM
168scm_current_pstate (void)
169#else
170SCM
171scm_current_pstate ()
172#endif
173{
174 return SCM_CADR (print_state_pool);
175}
176#endif
177
178#define PSTATE_SIZE 50L
179
180#ifdef __STDC__
181SCM
182scm_make_print_state (void)
183#else
184SCM
185scm_make_print_state ()
186#endif
187{
188 return scm_make_struct (SCM_CAR (print_state_pool), /* pstate type */
189 SCM_MAKINUM (PSTATE_SIZE),
190 SCM_EOL);
191}
a51ea417
MD
192
193#ifdef __STDC__
194static void
c62fbfe1 195grow_ref_stack (scm_print_state *pstate)
a51ea417
MD
196#else
197static void
c62fbfe1
MD
198grow_ref_stack (pstate)
199 scm_print_state *pstate;
a51ea417
MD
200#endif
201{
c62fbfe1
MD
202 int i, size = pstate->ceiling;
203 int total_size;
204 SCM handle;
205 SCM *data;
206 SCM_DEFER_INTS;
207 handle = pstate->handle;
208 data = (SCM *) pstate - scm_struct_n_extra_words;
209 total_size = ((SCM *) pstate)[scm_struct_i_n_words];
210 data = (SCM *) scm_must_realloc ((char *) data,
211 total_size,
212 total_size + size,
213 "grow_ref_stack");
214 pstate = (scm_print_state *) (data + scm_struct_n_extra_words);
215 ((SCM *) pstate)[scm_struct_i_n_words] = total_size + size;
216 pstate->ceiling += size;
217 for (i = size; i < pstate->ceiling; ++i)
218 pstate->ref_stack[i] = SCM_BOOL_F;
219 SCM_SETCDR (handle, pstate);
220 SCM_ALLOW_INTS;
a51ea417
MD
221}
222
223#ifdef __STDC__
224static void
c62fbfe1 225print_circref (SCM port, scm_print_state *pstate, SCM ref)
a51ea417
MD
226#else
227static void
c62fbfe1
MD
228print_circref (port, pstate, ref)
229 SCM port;
230 scm_print_state *pstate;
231 SCM ref;
a51ea417
MD
232#endif
233{
c62fbfe1
MD
234 register int i;
235 int self = pstate->top - 1;
236 i = pstate->top - 1;
237 if (SCM_CONSP (pstate->ref_stack[i]))
238 {
239 while (i > 0)
240 {
241 if (SCM_NCONSP (pstate->ref_stack[i - 1])
242 || SCM_CDR (pstate->ref_stack[i - 1]) != pstate->ref_stack[i])
243 break;
244 --i;
245 }
246 self = i;
247 }
248 for (i = pstate->top - 1; 1; --i)
249 if (pstate->ref_stack[i] == ref)
250 break;
251 scm_gen_putc ('#', port);
252 scm_intprint (i - self, 10, port);
253 scm_gen_putc ('#', port);
a51ea417
MD
254}
255
c62fbfe1 256/* Print generally. Handles both write and display according to PSTATE.
0f2d19dd 257 */
a51ea417 258
0f2d19dd
JB
259#ifdef __STDC__
260void
c62fbfe1 261scm_iprin1 (SCM exp, SCM port, scm_print_state *pstate)
0f2d19dd
JB
262#else
263void
c62fbfe1 264scm_iprin1 (exp, port, pstate)
0f2d19dd
JB
265 SCM exp;
266 SCM port;
c62fbfe1 267 scm_print_state *pstate;
0f2d19dd
JB
268#endif
269{
270 register long i;
271taloop:
272 switch (7 & (int) exp)
273 {
274 case 2:
275 case 6:
276 scm_intprint (SCM_INUM (exp), 10, port);
277 break;
278 case 4:
279 if (SCM_ICHRP (exp))
280 {
281 i = SCM_ICHR (exp);
c62fbfe1 282 scm_put_wchar (i, port, SCM_WRITINGP (pstate));
0f2d19dd
JB
283
284 }
a51ea417 285 else if (SCM_IFLAGP (exp)
0f2d19dd 286 && (SCM_ISYMNUM (exp) < (sizeof scm_isymnames / sizeof (char *))))
08b5b88c 287 scm_gen_puts (scm_regular_string, SCM_ISYMCHARS (exp), port);
0f2d19dd
JB
288 else if (SCM_ILOCP (exp))
289 {
290 scm_gen_puts (scm_regular_string, "#@", port);
291 scm_intprint ((long) SCM_IFRAME (exp), 10, port);
292 scm_gen_putc (SCM_ICDRP (exp) ? '-' : '+', port);
293 scm_intprint ((long) SCM_IDIST (exp), 10, port);
294 }
295 else
296 goto idef;
297 break;
298 case 1:
299 /* gloc */
300 scm_gen_puts (scm_regular_string, "#@", port);
301 exp = SCM_CAR (exp - 1);
302 goto taloop;
303 default:
304 idef:
305 scm_ipruk ("immediate", exp, port);
306 break;
307 case 0:
308 switch (SCM_TYP7 (exp))
309 {
310 case scm_tcs_cons_gloc:
311
312 if (SCM_CDR (SCM_CAR (exp) - 1L) == 0)
313 {
a51ea417 314 scm_gen_write (scm_regular_string, "#<struct ", sizeof ("#<struct ") - 1, port);
0f2d19dd
JB
315 scm_intprint(exp, 16, port);
316 scm_gen_putc ('>', port);
317 break;
318 }
319
320 case scm_tcs_cons_imcar:
321 case scm_tcs_cons_nimcar:
c62fbfe1
MD
322 ENTER_NESTED_DATA (pstate, exp, circref);
323 scm_iprlist ("(", exp, ')', port, pstate);
324 EXIT_NESTED_DATA (pstate);
a51ea417
MD
325 break;
326 circref:
c62fbfe1 327 print_circref (port, pstate, exp);
0f2d19dd
JB
328 break;
329 case scm_tcs_closures:
a51ea417
MD
330 if (SCM_NFALSEP (scm_procedure_p (SCM_PRINT_CLOSURE)))
331 {
332 SCM ans = scm_cons2 (exp, port,
c62fbfe1
MD
333 scm_cons (SCM_WRITINGP (pstate)
334 ? SCM_BOOL_T
335 : SCM_BOOL_F,
336 SCM_EOL));
a51ea417 337 ans = scm_apply (SCM_PRINT_CLOSURE, ans, SCM_EOL);
a51ea417 338 }
84f6a34a 339 else
0f2d19dd 340 {
84f6a34a 341 SCM name, code;
0f2d19dd 342 name = scm_procedure_property (exp, scm_i_name);
84f6a34a
MD
343 code = SCM_CODE (exp);
344 scm_gen_puts (scm_regular_string, "#<procedure ", port);
345 if (SCM_NIMP (name) && SCM_ROSTRINGP (name))
0f2d19dd 346 {
84f6a34a 347 scm_gen_puts (scm_regular_string, SCM_ROCHARS (name), port);
0f2d19dd 348 scm_gen_putc (' ', port);
0f2d19dd 349 }
c62fbfe1 350 scm_iprin1 (SCM_CAR (code), port, pstate);
84f6a34a
MD
351 if (SCM_PRINT_SOURCE_P)
352 {
353 code = scm_unmemocopy (SCM_CDR (code),
354 SCM_EXTEND_ENV (SCM_CAR (code),
355 SCM_EOL,
356 SCM_ENV (exp)));
c62fbfe1
MD
357 ENTER_NESTED_DATA (pstate, exp, circref);
358 scm_iprlist (" ", code, '>', port, pstate);
359 EXIT_NESTED_DATA (pstate);
84f6a34a
MD
360 }
361 else
362 scm_gen_putc ('>', port);
0f2d19dd
JB
363 }
364 break;
365 case scm_tc7_mb_string:
366 case scm_tc7_mb_substring:
c62fbfe1 367 scm_print_mb_string (exp, port, SCM_WRITINGP (pstate));
0f2d19dd
JB
368 break;
369 case scm_tc7_substring:
370 case scm_tc7_string:
c62fbfe1 371 if (SCM_WRITINGP (pstate))
0f2d19dd 372 {
dbef8851 373 scm_gen_putc ('"', port);
0f2d19dd
JB
374 for (i = 0; i < SCM_ROLENGTH (exp); ++i)
375 switch (SCM_ROCHARS (exp)[i])
376 {
dbef8851 377 case '"':
0f2d19dd
JB
378 case '\\':
379 scm_gen_putc ('\\', port);
380 default:
381 scm_gen_putc (SCM_ROCHARS (exp)[i], port);
382 }
dbef8851 383 scm_gen_putc ('"', port);
0f2d19dd
JB
384 break;
385 }
386 else
387 scm_gen_write (scm_regular_string, SCM_ROCHARS (exp),
388 (scm_sizet) SCM_ROLENGTH (exp),
389 port);
390 break;
391 case scm_tcs_symbols:
392 if (SCM_MB_STRINGP (exp))
393 {
394 scm_print_mb_symbol (exp, port);
395 break;
396 }
397 else
398 {
399 int pos;
400 int end;
401 int len;
402 char * str;
403 int weird;
404 int maybe_weird;
405 int mw_pos;
406
407 len = SCM_LENGTH (exp);
408 str = SCM_CHARS (exp);
409 scm_remember (&exp);
410 pos = 0;
411 weird = 0;
412 maybe_weird = 0;
413
414 if (len == 0)
415 scm_gen_write (scm_regular_string, "#{}#", 4, port);
416
417 for (end = pos; end < len; ++end)
418 switch (str[end])
419 {
420#ifdef BRACKETS_AS_PARENS
421 case '[':
422 case ']':
423#endif
424 case '(':
425 case ')':
dbef8851 426 case '"':
0f2d19dd
JB
427 case ';':
428 case SCM_WHITE_SPACES:
429 case SCM_LINE_INCREMENTORS:
430 weird_handler:
431 if (maybe_weird)
432 {
433 end = mw_pos;
434 maybe_weird = 0;
435 }
436 if (!weird)
437 {
438 scm_gen_write (scm_regular_string, "#{", 2, port);
439 weird = 1;
440 }
441 if (pos < end)
442 {
443 scm_gen_write (scm_regular_string, str + pos, end - pos, port);
444 }
445 {
446 char buf[2];
447 buf[0] = '\\';
448 buf[1] = str[end];
449 scm_gen_write (scm_regular_string, buf, 2, port);
450 }
451 pos = end + 1;
452 break;
453 case '\\':
454 if (weird)
455 goto weird_handler;
456 if (!maybe_weird)
457 {
458 maybe_weird = 1;
459 mw_pos = pos;
460 }
461 break;
462 case '}':
463 case '#':
464 if (weird)
465 goto weird_handler;
466 break;
467 default:
468 break;
469 }
470 if (pos < end)
471 scm_gen_write (scm_regular_string, str + pos, end - pos, port);
472 if (weird)
473 scm_gen_write (scm_regular_string, "}#", 2, port);
474 break;
475 }
476 case scm_tc7_wvect:
c62fbfe1 477 ENTER_NESTED_DATA (pstate, exp, circref);
0f2d19dd
JB
478 if (SCM_IS_WHVEC (exp))
479 scm_gen_puts (scm_regular_string, "#wh(", port);
480 else
481 scm_gen_puts (scm_regular_string, "#w(", port);
482 goto common_vector_printer;
483
484 case scm_tc7_vector:
c62fbfe1 485 ENTER_NESTED_DATA (pstate, exp, circref);
0f2d19dd
JB
486 scm_gen_puts (scm_regular_string, "#(", port);
487 common_vector_printer:
488 for (i = 0; i + 1 < SCM_LENGTH (exp); ++i)
489 {
490 /* CHECK_INTS; */
c62fbfe1 491 scm_iprin1 (SCM_VELTS (exp)[i], port, pstate);
0f2d19dd
JB
492 scm_gen_putc (' ', port);
493 }
494 if (i < SCM_LENGTH (exp))
495 {
496 /* CHECK_INTS; */
c62fbfe1 497 scm_iprin1 (SCM_VELTS (exp)[i], port, pstate);
0f2d19dd
JB
498 }
499 scm_gen_putc (')', port);
c62fbfe1 500 EXIT_NESTED_DATA (pstate);
0f2d19dd
JB
501 break;
502 case scm_tc7_bvect:
503 case scm_tc7_byvect:
504 case scm_tc7_svect:
505 case scm_tc7_ivect:
506 case scm_tc7_uvect:
507 case scm_tc7_fvect:
508 case scm_tc7_dvect:
509 case scm_tc7_cvect:
510#ifdef LONGLONGS
511 case scm_tc7_llvect:
512#endif
c62fbfe1 513 scm_raprin1 (exp, port, pstate);
0f2d19dd
JB
514 break;
515 case scm_tcs_subrs:
516 scm_gen_puts (scm_regular_string, "#<primitive-procedure ", port);
517 scm_gen_puts ((SCM_MB_STRINGP (SCM_SNAME(exp))
518 ? scm_mb_string
519 : scm_regular_string),
520 SCM_CHARS (SCM_SNAME (exp)), port);
521 scm_gen_putc ('>', port);
522 break;
523#ifdef CCLO
524 case scm_tc7_cclo:
525 scm_gen_puts (scm_regular_string, "#<compiled-closure ", port);
c62fbfe1 526 scm_iprin1 (SCM_CCLO_SUBR (exp), port, pstate);
0f2d19dd
JB
527 scm_gen_putc ('>', port);
528 break;
529#endif
530 case scm_tc7_contin:
531 scm_gen_puts (scm_regular_string, "#<continuation ", port);
532 scm_intprint (SCM_LENGTH (exp), 10, port);
533 scm_gen_puts (scm_regular_string, " @ ", port);
534 scm_intprint ((long) SCM_CHARS (exp), 16, port);
535 scm_gen_putc ('>', port);
536 break;
537 case scm_tc7_port:
538 i = SCM_PTOBNUM (exp);
c62fbfe1
MD
539 if (i < scm_numptob
540 && scm_ptobs[i].print
541 && (scm_ptobs[i].print) (exp, port, pstate))
0f2d19dd
JB
542 break;
543 goto punk;
544 case scm_tc7_smob:
c62fbfe1 545 ENTER_NESTED_DATA (pstate, exp, circref);
0f2d19dd
JB
546 i = SCM_SMOBNUM (exp);
547 if (i < scm_numsmob && scm_smobs[i].print
c62fbfe1 548 && (scm_smobs[i].print) (exp, port, pstate))
a51ea417 549 {
c62fbfe1 550 EXIT_NESTED_DATA (pstate);
a51ea417
MD
551 break;
552 }
c62fbfe1 553 EXIT_NESTED_DATA (pstate);
0f2d19dd 554 default:
a51ea417
MD
555 punk:
556 scm_ipruk ("type", exp, port);
0f2d19dd
JB
557 }
558 }
559}
560
c62fbfe1
MD
561/* Print states are necessary for circular reference safe printing.
562 * They are also expensive to allocate. Therefore print states are
563 * kept in a pool so that they can be reused.
564 */
a51ea417
MD
565#ifdef __STDC__
566void
c62fbfe1 567scm_prin1 (SCM exp, SCM port, int writingp)
a51ea417
MD
568#else
569void
c62fbfe1 570scm_prin1 (exp, port, writingp)
a51ea417
MD
571 SCM exp;
572 SCM port;
c62fbfe1 573 int writingp;
a51ea417
MD
574#endif
575{
c62fbfe1
MD
576 SCM handle = 0; /* Will GC protect the handle whilst unlinked */
577 scm_print_state *pstate;
578
579 /* First try to allocate a print state from the pool */
580 SCM_DEFER_INTS;
581 if (SCM_NNULLP (SCM_CDR (print_state_pool)))
582 {
583 handle = SCM_CDR (print_state_pool);
584 SCM_SETCDR (print_state_pool, SCM_CDDR (print_state_pool));
585 }
586 SCM_ALLOW_INTS;
587
588 if (!handle)
589 handle = scm_cons (scm_make_print_state (), SCM_EOL);
590
591 pstate = (scm_print_state *) SCM_STRUCT_DATA (SCM_CAR (handle));
592 pstate->writingp = writingp;
593 scm_iprin1 (exp, port, pstate);
594
595 /* Return print state to pool */
596 SCM_DEFER_INTS;
597 SCM_SETCDR (handle, SCM_CDR (print_state_pool));
598 SCM_SETCDR (print_state_pool, handle);
599 SCM_ALLOW_INTS;
a51ea417
MD
600}
601
0f2d19dd
JB
602
603/* Print an integer.
604 */
605#ifdef __STDC__
606void
607scm_intprint (long n, int radix, SCM port)
608#else
609void
610scm_intprint (n, radix, port)
611 long n;
612 int radix;
613 SCM port;
614#endif
615{
616 char num_buf[SCM_INTBUFLEN];
617 scm_gen_write (scm_regular_string, num_buf, scm_iint2str (n, radix, num_buf), port);
618}
619
620/* Print an object of unrecognized type.
621 */
622#ifdef __STDC__
623void
624scm_ipruk (char *hdr, SCM ptr, SCM port)
625#else
626void
627scm_ipruk (hdr, ptr, port)
628 char *hdr;
629 SCM ptr;
630 SCM port;
631#endif
632{
633 scm_gen_puts (scm_regular_string, "#<unknown-", port);
634 scm_gen_puts (scm_regular_string, hdr, port);
635 if (SCM_CELLP (ptr))
636 {
637 scm_gen_puts (scm_regular_string, " (0x", port);
638 scm_intprint (SCM_CAR (ptr), 16, port);
639 scm_gen_puts (scm_regular_string, " . 0x", port);
640 scm_intprint (SCM_CDR (ptr), 16, port);
641 scm_gen_puts (scm_regular_string, ") @", port);
642 }
643 scm_gen_puts (scm_regular_string, " 0x", port);
644 scm_intprint (ptr, 16, port);
645 scm_gen_putc ('>', port);
646}
647
648/* Print a list.
649 */
a51ea417 650
0f2d19dd
JB
651#ifdef __STDC__
652void
c62fbfe1 653scm_iprlist (char *hdr, SCM exp, char tlr, SCM port, scm_print_state *pstate)
0f2d19dd
JB
654#else
655void
c62fbfe1 656scm_iprlist (hdr, exp, tlr, port, pstate)
0f2d19dd
JB
657 char *hdr;
658 SCM exp;
659 char tlr;
660 SCM port;
c62fbfe1 661 scm_print_state *pstate;
0f2d19dd
JB
662#endif
663{
c62fbfe1
MD
664 register int i;
665 register SCM hare, tortoise;
666 int floor = pstate->top - 2;
0f2d19dd
JB
667 scm_gen_puts (scm_regular_string, hdr, port);
668 /* CHECK_INTS; */
c62fbfe1
MD
669 if (pstate->fancyp)
670 goto fancy_printing;
671
672 /* Run a hare and tortoise so that total time complexity will be
673 O(depth * N) instead of O(N^2). */
674 hare = SCM_CDR (exp);
675 tortoise = exp;
676 while (SCM_NIMP (hare))
677 {
678 if (hare == tortoise)
679 goto fancy_printing;
680 hare = SCM_CDR (hare);
681 if (SCM_IMP (hare))
682 break;
683 hare = SCM_CDR (hare);
684 tortoise = SCM_CDR (tortoise);
685 }
686
687 /* No cdr cycles intrinsic to this list */
688 scm_iprin1 (SCM_CAR (exp), port, pstate);
0f2d19dd
JB
689 exp = SCM_CDR (exp);
690 for (; SCM_NIMP (exp); exp = SCM_CDR (exp))
691 {
692 if (SCM_NECONSP (exp))
693 break;
c62fbfe1
MD
694 for (i = floor; i >= 0; --i)
695 if (pstate->ref_stack[i] == exp)
696 goto circref;
697 PUSH_REF (pstate, exp);
0f2d19dd
JB
698 scm_gen_putc (' ', port);
699 /* CHECK_INTS; */
c62fbfe1 700 scm_iprin1 (SCM_CAR (exp), port, pstate);
0f2d19dd
JB
701 }
702 if (SCM_NNULLP (exp))
703 {
704 scm_gen_puts (scm_regular_string, " . ", port);
c62fbfe1 705 scm_iprin1 (exp, port, pstate);
0f2d19dd 706 }
c62fbfe1 707
a51ea417 708end:
0f2d19dd 709 scm_gen_putc (tlr, port);
c62fbfe1 710 pstate->top = floor + 2;
a51ea417 711 return;
c62fbfe1
MD
712
713fancy_printing:
714 {
715 int n = pstate->length;
716
717 scm_iprin1 (SCM_CAR (exp), port, pstate);
718 exp = SCM_CDR (exp); --n;
719 for (; SCM_NIMP (exp); exp = SCM_CDR (exp))
720 {
721 if (SCM_NECONSP (exp))
722 break;
723 for (i = 0; i < pstate->top; ++i)
724 if (pstate->ref_stack[i] == exp)
725 goto fancy_circref;
726 if (pstate->fancyp)
727 {
728 if (n == 0)
729 {
730 scm_gen_puts (scm_regular_string, " ...", port);
731 goto skip_tail;
732 }
733 else
734 --n;
735 }
736 PUSH_REF(pstate, exp);
737 ++pstate->list_offset;
738 scm_gen_putc (' ', port);
739 /* CHECK_INTS; */
740 scm_iprin1 (SCM_CAR (exp), port, pstate);
741 }
742 }
743 if (SCM_NNULLP (exp))
744 {
745 scm_gen_puts (scm_regular_string, " . ", port);
746 scm_iprin1 (exp, port, pstate);
747 }
748skip_tail:
749 pstate->list_offset -= pstate->top - floor - 2;
a51ea417 750 goto end;
a51ea417 751
c62fbfe1
MD
752fancy_circref:
753 pstate->list_offset -= pstate->top - floor - 2;
754
755circref:
756 scm_gen_puts (scm_regular_string, " . ", port);
757 print_circref (port, pstate, exp);
758 goto end;
0f2d19dd
JB
759}
760
761\f
762
763SCM_PROC(s_write, "write", 1, 1, 0, scm_write);
764#ifdef __STDC__
765SCM
766scm_write (SCM obj, SCM port)
767#else
768SCM
769scm_write (obj, port)
770 SCM obj;
771 SCM port;
772#endif
773{
774 if (SCM_UNBNDP (port))
775 port = scm_cur_outp;
776 else
777 SCM_ASSERT (SCM_NIMP (port) && SCM_OPOUTPORTP (port), port, SCM_ARG2, s_write);
a51ea417 778 scm_prin1 (obj, port, 1);
0f2d19dd
JB
779#ifdef HAVE_PIPE
780# ifdef EPIPE
781 if (EPIPE == errno)
782 scm_close_port (port);
783# endif
784#endif
785 return SCM_UNSPECIFIED;
786}
787
788
789SCM_PROC(s_display, "display", 1, 1, 0, scm_display);
790#ifdef __STDC__
791SCM
792scm_display (SCM obj, SCM port)
793#else
794SCM
795scm_display (obj, port)
796 SCM obj;
797 SCM port;
798#endif
799{
800 if (SCM_UNBNDP (port))
801 port = scm_cur_outp;
802 else
803 SCM_ASSERT (SCM_NIMP (port) && SCM_OPOUTPORTP (port), port, SCM_ARG2, s_display);
a51ea417 804 scm_prin1 (obj, port, 0);
0f2d19dd
JB
805#ifdef HAVE_PIPE
806# ifdef EPIPE
807 if (EPIPE == errno)
808 scm_close_port (port);
809# endif
810#endif
811 return SCM_UNSPECIFIED;
812}
813
814SCM_PROC(s_newline, "newline", 0, 1, 0, scm_newline);
815#ifdef __STDC__
816SCM
817scm_newline(SCM port)
818#else
819SCM
820scm_newline (port)
821 SCM port;
822#endif
823{
824 if (SCM_UNBNDP (port))
825 port = scm_cur_outp;
826 else
827 SCM_ASSERT (SCM_NIMP (port) && SCM_OPOUTPORTP (port), port, SCM_ARG1, s_newline);
828 scm_gen_putc ('\n', port);
829#ifdef HAVE_PIPE
830# ifdef EPIPE
831 if (EPIPE == errno)
832 scm_close_port (port);
833 else
834# endif
835#endif
836 if (port == scm_cur_outp)
837 scm_fflush (port);
838 return SCM_UNSPECIFIED;
839}
840
841SCM_PROC(s_write_char, "write-char", 1, 1, 0, scm_write_char);
842#ifdef __STDC__
843SCM
844scm_write_char (SCM chr, SCM port)
845#else
846SCM
847scm_write_char (chr, port)
848 SCM chr;
849 SCM port;
850#endif
851{
852 if (SCM_UNBNDP (port))
853 port = scm_cur_outp;
854 else
855 SCM_ASSERT (SCM_NIMP (port) && SCM_OPOUTPORTP (port), port, SCM_ARG2, s_write_char);
856 SCM_ASSERT (SCM_ICHRP (chr), chr, SCM_ARG1, s_write_char);
857 scm_gen_putc ((int) SCM_ICHR (chr), port);
858#ifdef HAVE_PIPE
859# ifdef EPIPE
860 if (EPIPE == errno)
861 scm_close_port (port);
862# endif
863#endif
864 return SCM_UNSPECIFIED;
865}
866
867
868\f
869
870#ifdef __STDC__
871void
872scm_init_print (void)
873#else
874void
875scm_init_print ()
876#endif
877{
c62fbfe1 878 SCM vtable, type;
b7ff98dd 879 scm_init_opts (scm_print_options, scm_print_opts, SCM_N_PRINT_OPTIONS);
c62fbfe1
MD
880 vtable = scm_make_vtable_vtable (scm_make_struct_layout (scm_makfrom0str ("")), SCM_INUM0, SCM_EOL);
881 type = scm_make_struct (vtable,
882 SCM_INUM0,
883 scm_cons (scm_make_struct_layout (scm_makfrom0str (SCM_PRINT_STATE_LAYOUT)),
884 SCM_EOL));
885 print_state_pool = scm_permanent_object (scm_cons (type, SCM_EOL));
0f2d19dd
JB
886#include "print.x"
887}