* __scm.h, alist.c, alist.h, append.c, append.h, appinit.c,
[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);
1cc91f1b 109
e6e4c9af 110SCM
a51ea417
MD
111scm_print_options (setting)
112 SCM setting;
e6e4c9af 113{
a51ea417 114 SCM ans = scm_options (setting,
b7ff98dd
MD
115 scm_print_opts,
116 SCM_N_PRINT_OPTIONS,
117 s_print_options);
e6e4c9af
MD
118 return ans;
119}
e6e4c9af 120
0f2d19dd
JB
121\f
122/* {Printing of Scheme Objects}
123 */
124
a51ea417 125/* Detection of circular references.
c62fbfe1
MD
126 *
127 * Due to other constraints in the implementation, this code has bad
128 * time complexity (O (depth * N)), The printer code will be
129 * completely rewritten before next release of Guile. The new code
130 * will be O(N).
a51ea417 131 */
c62fbfe1 132#define PUSH_REF(pstate, obj) \
a51ea417 133{ \
c62fbfe1
MD
134 pstate->ref_stack[pstate->top++] = (obj); \
135 if (pstate->top == pstate->ceiling) \
136 grow_ref_stack (pstate); \
137}
a51ea417 138
c62fbfe1 139#define ENTER_NESTED_DATA(pstate, obj, label) \
a51ea417 140{ \
c62fbfe1
MD
141 register int i; \
142 for (i = 0; i < pstate->top; ++i) \
143 if (pstate->ref_stack[i] == (obj)) \
144 goto label; \
145 if (pstate->fancyp) \
146 { \
147 if (pstate->top - pstate->list_offset >= pstate->level) \
148 { \
149 scm_gen_putc ('#', port); \
150 return; \
151 } \
152 } \
153 PUSH_REF(pstate, obj); \
a51ea417
MD
154} \
155
c62fbfe1
MD
156#define EXIT_NESTED_DATA(pstate) { --pstate->top; }
157
158static SCM print_state_pool;
159
160#if 1 /* Used for debugging purposes */
161SCM_PROC(s_current_pstate, "current-pstate", 0, 0, 0, scm_current_pstate);
1cc91f1b 162
c62fbfe1
MD
163SCM
164scm_current_pstate ()
c62fbfe1
MD
165{
166 return SCM_CADR (print_state_pool);
167}
168#endif
169
170#define PSTATE_SIZE 50L
171
1cc91f1b 172
c62fbfe1
MD
173SCM
174scm_make_print_state ()
c62fbfe1
MD
175{
176 return scm_make_struct (SCM_CAR (print_state_pool), /* pstate type */
177 SCM_MAKINUM (PSTATE_SIZE),
178 SCM_EOL);
179}
a51ea417 180
1cc91f1b
JB
181
182static void grow_ref_stack SCM_P ((scm_print_state *pstate));
183
a51ea417 184static void
c62fbfe1
MD
185grow_ref_stack (pstate)
186 scm_print_state *pstate;
a51ea417 187{
c62fbfe1
MD
188 int i, size = pstate->ceiling;
189 int total_size;
190 SCM handle;
191 SCM *data;
192 SCM_DEFER_INTS;
193 handle = pstate->handle;
194 data = (SCM *) pstate - scm_struct_n_extra_words;
195 total_size = ((SCM *) pstate)[scm_struct_i_n_words];
196 data = (SCM *) scm_must_realloc ((char *) data,
197 total_size,
198 total_size + size,
199 "grow_ref_stack");
200 pstate = (scm_print_state *) (data + scm_struct_n_extra_words);
201 ((SCM *) pstate)[scm_struct_i_n_words] = total_size + size;
202 pstate->ceiling += size;
203 for (i = size; i < pstate->ceiling; ++i)
204 pstate->ref_stack[i] = SCM_BOOL_F;
205 SCM_SETCDR (handle, pstate);
206 SCM_ALLOW_INTS;
a51ea417
MD
207}
208
1cc91f1b
JB
209
210static void print_circref SCM_P ((SCM port, scm_print_state *pstate, SCM ref));
211
a51ea417 212static void
c62fbfe1
MD
213print_circref (port, pstate, ref)
214 SCM port;
215 scm_print_state *pstate;
216 SCM ref;
a51ea417 217{
c62fbfe1
MD
218 register int i;
219 int self = pstate->top - 1;
220 i = pstate->top - 1;
221 if (SCM_CONSP (pstate->ref_stack[i]))
222 {
223 while (i > 0)
224 {
225 if (SCM_NCONSP (pstate->ref_stack[i - 1])
226 || SCM_CDR (pstate->ref_stack[i - 1]) != pstate->ref_stack[i])
227 break;
228 --i;
229 }
230 self = i;
231 }
232 for (i = pstate->top - 1; 1; --i)
233 if (pstate->ref_stack[i] == ref)
234 break;
235 scm_gen_putc ('#', port);
236 scm_intprint (i - self, 10, port);
237 scm_gen_putc ('#', port);
a51ea417
MD
238}
239
c62fbfe1 240/* Print generally. Handles both write and display according to PSTATE.
0f2d19dd 241 */
a51ea417 242
1cc91f1b 243
0f2d19dd 244void
c62fbfe1 245scm_iprin1 (exp, port, pstate)
0f2d19dd
JB
246 SCM exp;
247 SCM port;
c62fbfe1 248 scm_print_state *pstate;
0f2d19dd
JB
249{
250 register long i;
251taloop:
252 switch (7 & (int) exp)
253 {
254 case 2:
255 case 6:
256 scm_intprint (SCM_INUM (exp), 10, port);
257 break;
258 case 4:
259 if (SCM_ICHRP (exp))
260 {
261 i = SCM_ICHR (exp);
c62fbfe1 262 scm_put_wchar (i, port, SCM_WRITINGP (pstate));
0f2d19dd
JB
263
264 }
a51ea417 265 else if (SCM_IFLAGP (exp)
0f2d19dd 266 && (SCM_ISYMNUM (exp) < (sizeof scm_isymnames / sizeof (char *))))
08b5b88c 267 scm_gen_puts (scm_regular_string, SCM_ISYMCHARS (exp), port);
0f2d19dd
JB
268 else if (SCM_ILOCP (exp))
269 {
270 scm_gen_puts (scm_regular_string, "#@", port);
271 scm_intprint ((long) SCM_IFRAME (exp), 10, port);
272 scm_gen_putc (SCM_ICDRP (exp) ? '-' : '+', port);
273 scm_intprint ((long) SCM_IDIST (exp), 10, port);
274 }
275 else
276 goto idef;
277 break;
278 case 1:
279 /* gloc */
280 scm_gen_puts (scm_regular_string, "#@", port);
281 exp = SCM_CAR (exp - 1);
282 goto taloop;
283 default:
284 idef:
285 scm_ipruk ("immediate", exp, port);
286 break;
287 case 0:
288 switch (SCM_TYP7 (exp))
289 {
290 case scm_tcs_cons_gloc:
291
292 if (SCM_CDR (SCM_CAR (exp) - 1L) == 0)
293 {
a51ea417 294 scm_gen_write (scm_regular_string, "#<struct ", sizeof ("#<struct ") - 1, port);
0f2d19dd
JB
295 scm_intprint(exp, 16, port);
296 scm_gen_putc ('>', port);
297 break;
298 }
299
300 case scm_tcs_cons_imcar:
301 case scm_tcs_cons_nimcar:
c62fbfe1
MD
302 ENTER_NESTED_DATA (pstate, exp, circref);
303 scm_iprlist ("(", exp, ')', port, pstate);
304 EXIT_NESTED_DATA (pstate);
a51ea417
MD
305 break;
306 circref:
c62fbfe1 307 print_circref (port, pstate, exp);
0f2d19dd
JB
308 break;
309 case scm_tcs_closures:
a51ea417
MD
310 if (SCM_NFALSEP (scm_procedure_p (SCM_PRINT_CLOSURE)))
311 {
312 SCM ans = scm_cons2 (exp, port,
c62fbfe1
MD
313 scm_cons (SCM_WRITINGP (pstate)
314 ? SCM_BOOL_T
315 : SCM_BOOL_F,
316 SCM_EOL));
a51ea417 317 ans = scm_apply (SCM_PRINT_CLOSURE, ans, SCM_EOL);
a51ea417 318 }
84f6a34a 319 else
0f2d19dd 320 {
84f6a34a 321 SCM name, code;
0f2d19dd 322 name = scm_procedure_property (exp, scm_i_name);
84f6a34a
MD
323 code = SCM_CODE (exp);
324 scm_gen_puts (scm_regular_string, "#<procedure ", port);
325 if (SCM_NIMP (name) && SCM_ROSTRINGP (name))
0f2d19dd 326 {
84f6a34a 327 scm_gen_puts (scm_regular_string, SCM_ROCHARS (name), port);
0f2d19dd 328 scm_gen_putc (' ', port);
0f2d19dd 329 }
c62fbfe1 330 scm_iprin1 (SCM_CAR (code), port, pstate);
84f6a34a
MD
331 if (SCM_PRINT_SOURCE_P)
332 {
333 code = scm_unmemocopy (SCM_CDR (code),
334 SCM_EXTEND_ENV (SCM_CAR (code),
335 SCM_EOL,
336 SCM_ENV (exp)));
c62fbfe1
MD
337 ENTER_NESTED_DATA (pstate, exp, circref);
338 scm_iprlist (" ", code, '>', port, pstate);
339 EXIT_NESTED_DATA (pstate);
84f6a34a
MD
340 }
341 else
342 scm_gen_putc ('>', port);
0f2d19dd
JB
343 }
344 break;
345 case scm_tc7_mb_string:
346 case scm_tc7_mb_substring:
c62fbfe1 347 scm_print_mb_string (exp, port, SCM_WRITINGP (pstate));
0f2d19dd
JB
348 break;
349 case scm_tc7_substring:
350 case scm_tc7_string:
c62fbfe1 351 if (SCM_WRITINGP (pstate))
0f2d19dd 352 {
dbef8851 353 scm_gen_putc ('"', port);
0f2d19dd
JB
354 for (i = 0; i < SCM_ROLENGTH (exp); ++i)
355 switch (SCM_ROCHARS (exp)[i])
356 {
dbef8851 357 case '"':
0f2d19dd
JB
358 case '\\':
359 scm_gen_putc ('\\', port);
360 default:
361 scm_gen_putc (SCM_ROCHARS (exp)[i], port);
362 }
dbef8851 363 scm_gen_putc ('"', port);
0f2d19dd
JB
364 break;
365 }
366 else
367 scm_gen_write (scm_regular_string, SCM_ROCHARS (exp),
368 (scm_sizet) SCM_ROLENGTH (exp),
369 port);
370 break;
371 case scm_tcs_symbols:
372 if (SCM_MB_STRINGP (exp))
373 {
374 scm_print_mb_symbol (exp, port);
375 break;
376 }
377 else
378 {
379 int pos;
380 int end;
381 int len;
382 char * str;
383 int weird;
384 int maybe_weird;
385 int mw_pos;
386
387 len = SCM_LENGTH (exp);
388 str = SCM_CHARS (exp);
389 scm_remember (&exp);
390 pos = 0;
391 weird = 0;
392 maybe_weird = 0;
393
394 if (len == 0)
395 scm_gen_write (scm_regular_string, "#{}#", 4, port);
396
397 for (end = pos; end < len; ++end)
398 switch (str[end])
399 {
400#ifdef BRACKETS_AS_PARENS
401 case '[':
402 case ']':
403#endif
404 case '(':
405 case ')':
dbef8851 406 case '"':
0f2d19dd
JB
407 case ';':
408 case SCM_WHITE_SPACES:
409 case SCM_LINE_INCREMENTORS:
410 weird_handler:
411 if (maybe_weird)
412 {
413 end = mw_pos;
414 maybe_weird = 0;
415 }
416 if (!weird)
417 {
418 scm_gen_write (scm_regular_string, "#{", 2, port);
419 weird = 1;
420 }
421 if (pos < end)
422 {
423 scm_gen_write (scm_regular_string, str + pos, end - pos, port);
424 }
425 {
426 char buf[2];
427 buf[0] = '\\';
428 buf[1] = str[end];
429 scm_gen_write (scm_regular_string, buf, 2, port);
430 }
431 pos = end + 1;
432 break;
433 case '\\':
434 if (weird)
435 goto weird_handler;
436 if (!maybe_weird)
437 {
438 maybe_weird = 1;
439 mw_pos = pos;
440 }
441 break;
442 case '}':
443 case '#':
444 if (weird)
445 goto weird_handler;
446 break;
447 default:
448 break;
449 }
450 if (pos < end)
451 scm_gen_write (scm_regular_string, str + pos, end - pos, port);
452 if (weird)
453 scm_gen_write (scm_regular_string, "}#", 2, port);
454 break;
455 }
456 case scm_tc7_wvect:
c62fbfe1 457 ENTER_NESTED_DATA (pstate, exp, circref);
0f2d19dd
JB
458 if (SCM_IS_WHVEC (exp))
459 scm_gen_puts (scm_regular_string, "#wh(", port);
460 else
461 scm_gen_puts (scm_regular_string, "#w(", port);
462 goto common_vector_printer;
463
464 case scm_tc7_vector:
c62fbfe1 465 ENTER_NESTED_DATA (pstate, exp, circref);
0f2d19dd
JB
466 scm_gen_puts (scm_regular_string, "#(", port);
467 common_vector_printer:
468 for (i = 0; i + 1 < SCM_LENGTH (exp); ++i)
469 {
470 /* CHECK_INTS; */
c62fbfe1 471 scm_iprin1 (SCM_VELTS (exp)[i], port, pstate);
0f2d19dd
JB
472 scm_gen_putc (' ', port);
473 }
474 if (i < SCM_LENGTH (exp))
475 {
476 /* CHECK_INTS; */
c62fbfe1 477 scm_iprin1 (SCM_VELTS (exp)[i], port, pstate);
0f2d19dd
JB
478 }
479 scm_gen_putc (')', port);
c62fbfe1 480 EXIT_NESTED_DATA (pstate);
0f2d19dd
JB
481 break;
482 case scm_tc7_bvect:
483 case scm_tc7_byvect:
484 case scm_tc7_svect:
485 case scm_tc7_ivect:
486 case scm_tc7_uvect:
487 case scm_tc7_fvect:
488 case scm_tc7_dvect:
489 case scm_tc7_cvect:
490#ifdef LONGLONGS
491 case scm_tc7_llvect:
492#endif
c62fbfe1 493 scm_raprin1 (exp, port, pstate);
0f2d19dd
JB
494 break;
495 case scm_tcs_subrs:
496 scm_gen_puts (scm_regular_string, "#<primitive-procedure ", port);
497 scm_gen_puts ((SCM_MB_STRINGP (SCM_SNAME(exp))
498 ? scm_mb_string
499 : scm_regular_string),
500 SCM_CHARS (SCM_SNAME (exp)), port);
501 scm_gen_putc ('>', port);
502 break;
503#ifdef CCLO
504 case scm_tc7_cclo:
505 scm_gen_puts (scm_regular_string, "#<compiled-closure ", port);
c62fbfe1 506 scm_iprin1 (SCM_CCLO_SUBR (exp), port, pstate);
0f2d19dd
JB
507 scm_gen_putc ('>', port);
508 break;
509#endif
510 case scm_tc7_contin:
511 scm_gen_puts (scm_regular_string, "#<continuation ", port);
512 scm_intprint (SCM_LENGTH (exp), 10, port);
513 scm_gen_puts (scm_regular_string, " @ ", port);
514 scm_intprint ((long) SCM_CHARS (exp), 16, port);
515 scm_gen_putc ('>', port);
516 break;
517 case scm_tc7_port:
518 i = SCM_PTOBNUM (exp);
c62fbfe1
MD
519 if (i < scm_numptob
520 && scm_ptobs[i].print
521 && (scm_ptobs[i].print) (exp, port, pstate))
0f2d19dd
JB
522 break;
523 goto punk;
524 case scm_tc7_smob:
c62fbfe1 525 ENTER_NESTED_DATA (pstate, exp, circref);
0f2d19dd
JB
526 i = SCM_SMOBNUM (exp);
527 if (i < scm_numsmob && scm_smobs[i].print
c62fbfe1 528 && (scm_smobs[i].print) (exp, port, pstate))
a51ea417 529 {
c62fbfe1 530 EXIT_NESTED_DATA (pstate);
a51ea417
MD
531 break;
532 }
c62fbfe1 533 EXIT_NESTED_DATA (pstate);
0f2d19dd 534 default:
a51ea417
MD
535 punk:
536 scm_ipruk ("type", exp, port);
0f2d19dd
JB
537 }
538 }
539}
540
c62fbfe1
MD
541/* Print states are necessary for circular reference safe printing.
542 * They are also expensive to allocate. Therefore print states are
543 * kept in a pool so that they can be reused.
544 */
1cc91f1b 545
a51ea417 546void
c62fbfe1 547scm_prin1 (exp, port, writingp)
a51ea417
MD
548 SCM exp;
549 SCM port;
c62fbfe1 550 int writingp;
a51ea417 551{
c62fbfe1
MD
552 SCM handle = 0; /* Will GC protect the handle whilst unlinked */
553 scm_print_state *pstate;
554
555 /* First try to allocate a print state from the pool */
556 SCM_DEFER_INTS;
557 if (SCM_NNULLP (SCM_CDR (print_state_pool)))
558 {
559 handle = SCM_CDR (print_state_pool);
560 SCM_SETCDR (print_state_pool, SCM_CDDR (print_state_pool));
561 }
562 SCM_ALLOW_INTS;
563
564 if (!handle)
565 handle = scm_cons (scm_make_print_state (), SCM_EOL);
566
567 pstate = (scm_print_state *) SCM_STRUCT_DATA (SCM_CAR (handle));
568 pstate->writingp = writingp;
569 scm_iprin1 (exp, port, pstate);
570
571 /* Return print state to pool */
572 SCM_DEFER_INTS;
573 SCM_SETCDR (handle, SCM_CDR (print_state_pool));
574 SCM_SETCDR (print_state_pool, handle);
575 SCM_ALLOW_INTS;
a51ea417
MD
576}
577
0f2d19dd
JB
578
579/* Print an integer.
580 */
1cc91f1b 581
0f2d19dd
JB
582void
583scm_intprint (n, radix, port)
584 long n;
585 int radix;
586 SCM port;
0f2d19dd
JB
587{
588 char num_buf[SCM_INTBUFLEN];
589 scm_gen_write (scm_regular_string, num_buf, scm_iint2str (n, radix, num_buf), port);
590}
591
592/* Print an object of unrecognized type.
593 */
1cc91f1b 594
0f2d19dd
JB
595void
596scm_ipruk (hdr, ptr, port)
597 char *hdr;
598 SCM ptr;
599 SCM port;
0f2d19dd
JB
600{
601 scm_gen_puts (scm_regular_string, "#<unknown-", port);
602 scm_gen_puts (scm_regular_string, hdr, port);
603 if (SCM_CELLP (ptr))
604 {
605 scm_gen_puts (scm_regular_string, " (0x", port);
606 scm_intprint (SCM_CAR (ptr), 16, port);
607 scm_gen_puts (scm_regular_string, " . 0x", port);
608 scm_intprint (SCM_CDR (ptr), 16, port);
609 scm_gen_puts (scm_regular_string, ") @", port);
610 }
611 scm_gen_puts (scm_regular_string, " 0x", port);
612 scm_intprint (ptr, 16, port);
613 scm_gen_putc ('>', port);
614}
615
616/* Print a list.
617 */
a51ea417 618
1cc91f1b 619
0f2d19dd 620void
c62fbfe1 621scm_iprlist (hdr, exp, tlr, port, pstate)
0f2d19dd
JB
622 char *hdr;
623 SCM exp;
624 char tlr;
625 SCM port;
c62fbfe1 626 scm_print_state *pstate;
0f2d19dd 627{
c62fbfe1
MD
628 register int i;
629 register SCM hare, tortoise;
630 int floor = pstate->top - 2;
0f2d19dd
JB
631 scm_gen_puts (scm_regular_string, hdr, port);
632 /* CHECK_INTS; */
c62fbfe1
MD
633 if (pstate->fancyp)
634 goto fancy_printing;
635
636 /* Run a hare and tortoise so that total time complexity will be
637 O(depth * N) instead of O(N^2). */
638 hare = SCM_CDR (exp);
639 tortoise = exp;
2fab3faa 640 while (SCM_NIMP (hare) && SCM_ECONSP (hare))
c62fbfe1
MD
641 {
642 if (hare == tortoise)
643 goto fancy_printing;
644 hare = SCM_CDR (hare);
2fab3faa 645 if (SCM_IMP (hare) || SCM_NECONSP (hare))
c62fbfe1
MD
646 break;
647 hare = SCM_CDR (hare);
648 tortoise = SCM_CDR (tortoise);
649 }
650
651 /* No cdr cycles intrinsic to this list */
652 scm_iprin1 (SCM_CAR (exp), port, pstate);
0f2d19dd
JB
653 exp = SCM_CDR (exp);
654 for (; SCM_NIMP (exp); exp = SCM_CDR (exp))
655 {
656 if (SCM_NECONSP (exp))
657 break;
c62fbfe1
MD
658 for (i = floor; i >= 0; --i)
659 if (pstate->ref_stack[i] == exp)
660 goto circref;
661 PUSH_REF (pstate, exp);
0f2d19dd
JB
662 scm_gen_putc (' ', port);
663 /* CHECK_INTS; */
c62fbfe1 664 scm_iprin1 (SCM_CAR (exp), port, pstate);
0f2d19dd
JB
665 }
666 if (SCM_NNULLP (exp))
667 {
668 scm_gen_puts (scm_regular_string, " . ", port);
c62fbfe1 669 scm_iprin1 (exp, port, pstate);
0f2d19dd 670 }
c62fbfe1 671
a51ea417 672end:
0f2d19dd 673 scm_gen_putc (tlr, port);
c62fbfe1 674 pstate->top = floor + 2;
a51ea417 675 return;
c62fbfe1
MD
676
677fancy_printing:
678 {
679 int n = pstate->length;
680
681 scm_iprin1 (SCM_CAR (exp), port, pstate);
682 exp = SCM_CDR (exp); --n;
683 for (; SCM_NIMP (exp); exp = SCM_CDR (exp))
684 {
685 if (SCM_NECONSP (exp))
686 break;
687 for (i = 0; i < pstate->top; ++i)
688 if (pstate->ref_stack[i] == exp)
689 goto fancy_circref;
690 if (pstate->fancyp)
691 {
692 if (n == 0)
693 {
694 scm_gen_puts (scm_regular_string, " ...", port);
695 goto skip_tail;
696 }
697 else
698 --n;
699 }
700 PUSH_REF(pstate, exp);
701 ++pstate->list_offset;
702 scm_gen_putc (' ', port);
703 /* CHECK_INTS; */
704 scm_iprin1 (SCM_CAR (exp), port, pstate);
705 }
706 }
707 if (SCM_NNULLP (exp))
708 {
709 scm_gen_puts (scm_regular_string, " . ", port);
710 scm_iprin1 (exp, port, pstate);
711 }
712skip_tail:
713 pstate->list_offset -= pstate->top - floor - 2;
a51ea417 714 goto end;
a51ea417 715
c62fbfe1
MD
716fancy_circref:
717 pstate->list_offset -= pstate->top - floor - 2;
718
719circref:
720 scm_gen_puts (scm_regular_string, " . ", port);
721 print_circref (port, pstate, exp);
722 goto end;
0f2d19dd
JB
723}
724
725\f
726
727SCM_PROC(s_write, "write", 1, 1, 0, scm_write);
1cc91f1b 728
0f2d19dd
JB
729SCM
730scm_write (obj, port)
731 SCM obj;
732 SCM port;
0f2d19dd
JB
733{
734 if (SCM_UNBNDP (port))
735 port = scm_cur_outp;
736 else
737 SCM_ASSERT (SCM_NIMP (port) && SCM_OPOUTPORTP (port), port, SCM_ARG2, s_write);
a51ea417 738 scm_prin1 (obj, port, 1);
0f2d19dd
JB
739#ifdef HAVE_PIPE
740# ifdef EPIPE
741 if (EPIPE == errno)
742 scm_close_port (port);
743# endif
744#endif
745 return SCM_UNSPECIFIED;
746}
747
748
749SCM_PROC(s_display, "display", 1, 1, 0, scm_display);
1cc91f1b 750
0f2d19dd
JB
751SCM
752scm_display (obj, port)
753 SCM obj;
754 SCM port;
0f2d19dd
JB
755{
756 if (SCM_UNBNDP (port))
757 port = scm_cur_outp;
758 else
759 SCM_ASSERT (SCM_NIMP (port) && SCM_OPOUTPORTP (port), port, SCM_ARG2, s_display);
a51ea417 760 scm_prin1 (obj, port, 0);
0f2d19dd
JB
761#ifdef HAVE_PIPE
762# ifdef EPIPE
763 if (EPIPE == errno)
764 scm_close_port (port);
765# endif
766#endif
767 return SCM_UNSPECIFIED;
768}
769
770SCM_PROC(s_newline, "newline", 0, 1, 0, scm_newline);
1cc91f1b 771
0f2d19dd
JB
772SCM
773scm_newline (port)
774 SCM port;
0f2d19dd
JB
775{
776 if (SCM_UNBNDP (port))
777 port = scm_cur_outp;
778 else
779 SCM_ASSERT (SCM_NIMP (port) && SCM_OPOUTPORTP (port), port, SCM_ARG1, s_newline);
780 scm_gen_putc ('\n', port);
781#ifdef HAVE_PIPE
782# ifdef EPIPE
783 if (EPIPE == errno)
784 scm_close_port (port);
785 else
786# endif
787#endif
788 if (port == scm_cur_outp)
789 scm_fflush (port);
790 return SCM_UNSPECIFIED;
791}
792
793SCM_PROC(s_write_char, "write-char", 1, 1, 0, scm_write_char);
1cc91f1b 794
0f2d19dd
JB
795SCM
796scm_write_char (chr, port)
797 SCM chr;
798 SCM port;
0f2d19dd
JB
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_write_char);
804 SCM_ASSERT (SCM_ICHRP (chr), chr, SCM_ARG1, s_write_char);
805 scm_gen_putc ((int) SCM_ICHR (chr), port);
806#ifdef HAVE_PIPE
807# ifdef EPIPE
808 if (EPIPE == errno)
809 scm_close_port (port);
810# endif
811#endif
812 return SCM_UNSPECIFIED;
813}
814
815
816\f
817
1cc91f1b 818
0f2d19dd
JB
819void
820scm_init_print ()
0f2d19dd 821{
c62fbfe1 822 SCM vtable, type;
b7ff98dd 823 scm_init_opts (scm_print_options, scm_print_opts, SCM_N_PRINT_OPTIONS);
c62fbfe1
MD
824 vtable = scm_make_vtable_vtable (scm_make_struct_layout (scm_makfrom0str ("")), SCM_INUM0, SCM_EOL);
825 type = scm_make_struct (vtable,
826 SCM_INUM0,
827 scm_cons (scm_make_struct_layout (scm_makfrom0str (SCM_PRINT_STATE_LAYOUT)),
828 SCM_EOL));
829 print_state_pool = scm_permanent_object (scm_cons (type, SCM_EOL));
0f2d19dd
JB
830#include "print.x"
831}