*** empty log message ***
[bpt/guile.git] / libguile / print.c
CommitLineData
15635be5 1/* Copyright (C) 1995-1999,2000,2001, 2002, 2003 Free Software Foundation, Inc.
0f2d19dd 2 *
73be1d9e
MV
3 * This library is free software; you can redistribute it and/or
4 * modify it under the terms of the GNU Lesser General Public
5 * License as published by the Free Software Foundation; either
6 * version 2.1 of the License, or (at your option) any later version.
0f2d19dd 7 *
73be1d9e
MV
8 * This library 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 GNU
11 * Lesser General Public License for more details.
0f2d19dd 12 *
73be1d9e
MV
13 * You should have received a copy of the GNU Lesser General Public
14 * License along with this library; if not, write to the Free Software
15 * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
16 */
1bbd0b84 17
1bbd0b84 18
0f2d19dd
JB
19\f
20
e6e2e95a
MD
21#include <errno.h>
22
a0599745
MD
23#include "libguile/_scm.h"
24#include "libguile/chars.h"
a002f1a2 25#include "libguile/continuations.h"
a0599745
MD
26#include "libguile/smob.h"
27#include "libguile/eval.h"
28#include "libguile/macros.h"
29#include "libguile/procprop.h"
30#include "libguile/read.h"
31#include "libguile/weaks.h"
32#include "libguile/unif.h"
33#include "libguile/alist.h"
34#include "libguile/struct.h"
35#include "libguile/objects.h"
36#include "libguile/ports.h"
37#include "libguile/root.h"
38#include "libguile/strings.h"
39#include "libguile/strports.h"
40#include "libguile/vectors.h"
c96d76b8 41#include "libguile/lang.h"
a0599745
MD
42
43#include "libguile/validate.h"
44#include "libguile/print.h"
0f2d19dd
JB
45\f
46
47/* {Names of immediate symbols}
48 *
49 * This table must agree with the declarations in scm.h: {Immediate Symbols}.
50 */
51
e17d318f
DH
52/* This table must agree with the list of flags in tags.h. */
53static const char *iflagnames[] =
54{
55 "#f",
56 "#t",
57 "#<undefined>",
58 "#<eof>",
59 "()",
60 "#<unspecified>",
61
62 /* Unbound slot marker for GOOPS. For internal use in GOOPS only. */
63 "#<unbound>",
64
65 /* Elisp nil value. This is its Scheme name; whenever it's printed in
66 * Elisp, it should appear as the symbol `nil'. */
67 "#nil"
68};
69
70/* This table must agree with the list of SCM_IM_ constants in tags.h */
0f2d19dd
JB
71char *scm_isymnames[] =
72{
e17d318f
DH
73 /* Short instructions */
74
0f2d19dd
JB
75 "#@and",
76 "#@begin",
77 "#@case",
78 "#@cond",
79 "#@do",
80 "#@if",
81 "#@lambda",
82 "#@let",
83 "#@let*",
84 "#@letrec",
85 "#@or",
86 "#@quote",
87 "#@set!",
e17d318f
DH
88
89
90 /* Long instructions */
91
0f2d19dd 92 "#@define",
0f2d19dd
JB
93 "#@apply",
94 "#@call-with-current-continuation",
4df91bd6 95 "#@dispatch",
43c667e9
MD
96 "#@slot-ref",
97 "#@slot-set!",
5623a9b4 98 "#@delay",
28d52ebb 99 "#@future",
24d1fde8 100 "#@call-with-values",
2a6f7afe
DH
101 "#@else",
102 "#@arrow",
24d1fde8 103
e17d318f
DH
104 /* Multi-language support */
105 "#@nil-cond",
106 "#@bind"
0f2d19dd
JB
107};
108
92c2555f 109scm_t_option scm_print_opts[] = {
726d810a
DH
110 { SCM_OPTION_SCM, "closure-hook", SCM_UNPACK (SCM_BOOL_F),
111 "Hook for printing closures (should handle macros as well)." },
84f6a34a
MD
112 { SCM_OPTION_BOOLEAN, "source", 0,
113 "Print closures with source." }
e6e4c9af
MD
114};
115
a1ec6916 116SCM_DEFINE (scm_print_options, "print-options-interface", 0, 1, 0,
1bbd0b84 117 (SCM setting),
71331188 118 "Option interface for the print options. Instead of using\n"
1dd05fd8
MG
119 "this procedure directly, use the procedures\n"
120 "@code{print-enable}, @code{print-disable}, @code{print-set!}\n"
121 "and @code{print-options}.")
1bbd0b84 122#define FUNC_NAME s_scm_print_options
e6e4c9af 123{
a51ea417 124 SCM ans = scm_options (setting,
b7ff98dd
MD
125 scm_print_opts,
126 SCM_N_PRINT_OPTIONS,
1bbd0b84 127 FUNC_NAME);
e6e4c9af
MD
128 return ans;
129}
1bbd0b84 130#undef FUNC_NAME
e6e4c9af 131
0f2d19dd
JB
132\f
133/* {Printing of Scheme Objects}
134 */
135
a51ea417 136/* Detection of circular references.
c62fbfe1
MD
137 *
138 * Due to other constraints in the implementation, this code has bad
5d46ebe3
MD
139 * time complexity (O (depth * N)), The printer code can be
140 * rewritten to be O(N).
a51ea417 141 */
c62fbfe1 142#define PUSH_REF(pstate, obj) \
1bbd0b84 143do { \
c62fbfe1
MD
144 pstate->ref_stack[pstate->top++] = (obj); \
145 if (pstate->top == pstate->ceiling) \
146 grow_ref_stack (pstate); \
1bbd0b84 147} while(0)
a51ea417 148
c62fbfe1 149#define ENTER_NESTED_DATA(pstate, obj, label) \
1bbd0b84 150do { \
5ca6dc39 151 register unsigned long i; \
c62fbfe1 152 for (i = 0; i < pstate->top; ++i) \
230d095f 153 if (SCM_EQ_P (pstate->ref_stack[i], (obj))) \
c62fbfe1
MD
154 goto label; \
155 if (pstate->fancyp) \
156 { \
157 if (pstate->top - pstate->list_offset >= pstate->level) \
158 { \
b7f3516f 159 scm_putc ('#', port); \
c62fbfe1
MD
160 return; \
161 } \
162 } \
163 PUSH_REF(pstate, obj); \
1bbd0b84 164} while(0)
a51ea417 165
c62fbfe1
MD
166#define EXIT_NESTED_DATA(pstate) { --pstate->top; }
167
d5cf5324
DH
168SCM scm_print_state_vtable = SCM_BOOL_F;
169static SCM print_state_pool = SCM_EOL;
dfd03fb9 170SCM_MUTEX (print_state_mutex);
c4f37e80 171
f843a84c 172#ifdef GUILE_DEBUG /* Used for debugging purposes */
1cc91f1b 173
3b3b36dd 174SCM_DEFINE (scm_current_pstate, "current-pstate", 0, 0, 0,
1bbd0b84 175 (),
d5cf5324 176 "Return the current-pstate -- the car of the\n"
5352393c
MG
177 "@code{print_state_pool}. @code{current-pstate} is only\n"
178 "included in @code{--enable-guile-debug} builds.")
1bbd0b84 179#define FUNC_NAME s_scm_current_pstate
c62fbfe1 180{
d5cf5324
DH
181 if (!SCM_NULLP (print_state_pool))
182 return SCM_CAR (print_state_pool);
a0adfbf0 183 else
0a284a4e 184 return SCM_BOOL_F;
c62fbfe1 185}
1bbd0b84
GB
186#undef FUNC_NAME
187
c62fbfe1
MD
188#endif
189
190#define PSTATE_SIZE 50L
191
698c0295 192static SCM
1bbd0b84 193make_print_state (void)
698c0295 194{
d5cf5324
DH
195 SCM print_state
196 = scm_make_struct (scm_print_state_vtable, SCM_INUM0, SCM_EOL);
bf685b6d 197 scm_print_state *pstate = SCM_PRINT_STATE (print_state);
00ffa0e7 198 pstate->ref_vect = scm_c_make_vector (PSTATE_SIZE, SCM_UNDEFINED);
34d19ef6 199 pstate->ref_stack = SCM_WRITABLE_VELTS (pstate->ref_vect);
b17004b8 200 pstate->ceiling = SCM_VECTOR_LENGTH (pstate->ref_vect);
698c0295
MD
201 return print_state;
202}
1cc91f1b 203
c62fbfe1
MD
204SCM
205scm_make_print_state ()
c62fbfe1 206{
230d095f 207 SCM answer = SCM_BOOL_F;
698c0295
MD
208
209 /* First try to allocate a print state from the pool */
dfd03fb9 210 scm_i_plugin_mutex_lock (&print_state_mutex);
d5cf5324 211 if (!SCM_NULLP (print_state_pool))
698c0295 212 {
d5cf5324
DH
213 answer = SCM_CAR (print_state_pool);
214 print_state_pool = SCM_CDR (print_state_pool);
698c0295 215 }
dfd03fb9 216 scm_i_plugin_mutex_unlock (&print_state_mutex);
698c0295 217
230d095f 218 return SCM_FALSEP (answer) ? make_print_state () : answer;
c62fbfe1 219}
a51ea417 220
698c0295 221void
6e8d25a6 222scm_free_print_state (SCM print_state)
698c0295
MD
223{
224 SCM handle;
225 scm_print_state *pstate = SCM_PRINT_STATE (print_state);
226 /* Cleanup before returning print state to pool.
227 * It is better to do it here. Doing it in scm_prin1
228 * would cost more since that function is called much more
229 * often.
230 */
231 pstate->fancyp = 0;
bb35f315 232 pstate->revealed = 0;
dfd03fb9 233 scm_i_plugin_mutex_lock (&print_state_mutex);
16d4699b 234 handle = scm_cons (print_state, print_state_pool);
d5cf5324 235 print_state_pool = handle;
dfd03fb9
MD
236 scm_i_plugin_mutex_unlock (&print_state_mutex);
237}
238
239SCM
240scm_i_port_with_print_state (SCM port, SCM print_state)
241{
242 if (SCM_UNBNDP (print_state))
243 {
244 if (SCM_PORT_WITH_PS_P (port))
245 return port;
246 else
247 print_state = scm_make_print_state ();
248 /* port does not need to be coerced since it doesn't have ps */
249 }
250 else
251 port = SCM_COERCE_OUTPORT (port);
252 SCM_RETURN_NEWSMOB (scm_tc16_port_with_ps,
253 SCM_UNPACK (scm_cons (port, print_state)));
698c0295 254}
1cc91f1b 255
a51ea417 256static void
1bbd0b84 257grow_ref_stack (scm_print_state *pstate)
a51ea417 258{
b17004b8 259 unsigned long int old_size = SCM_VECTOR_LENGTH (pstate->ref_vect);
34d19ef6 260 SCM const *old_elts = SCM_VELTS (pstate->ref_vect);
b17004b8 261 unsigned long int new_size = 2 * pstate->ceiling;
00ffa0e7 262 SCM new_vect = scm_c_make_vector (new_size, SCM_UNDEFINED);
b17004b8
DH
263 unsigned long int i;
264
265 for (i = 0; i != old_size; ++i)
34d19ef6 266 SCM_VECTOR_SET (new_vect, i, old_elts [i]);
b17004b8
DH
267
268 pstate->ref_vect = new_vect;
34d19ef6 269 pstate->ref_stack = SCM_WRITABLE_VELTS(new_vect);
bf685b6d 270 pstate->ceiling = new_size;
a51ea417
MD
271}
272
1cc91f1b 273
a51ea417 274static void
34d19ef6 275print_circref (SCM port, scm_print_state *pstate, SCM ref)
a51ea417 276{
c014a02e
ML
277 register long i;
278 long self = pstate->top - 1;
c62fbfe1
MD
279 i = pstate->top - 1;
280 if (SCM_CONSP (pstate->ref_stack[i]))
281 {
282 while (i > 0)
283 {
d5cf5324 284 if (!SCM_CONSP (pstate->ref_stack[i - 1])
230d095f
DH
285 || !SCM_EQ_P (SCM_CDR (pstate->ref_stack[i - 1]),
286 pstate->ref_stack[i]))
c62fbfe1
MD
287 break;
288 --i;
289 }
290 self = i;
291 }
292 for (i = pstate->top - 1; 1; --i)
230d095f 293 if (SCM_EQ_P (pstate->ref_stack[i], ref))
c62fbfe1 294 break;
b7f3516f 295 scm_putc ('#', port);
c62fbfe1 296 scm_intprint (i - self, 10, port);
b7f3516f 297 scm_putc ('#', port);
a51ea417
MD
298}
299
6662998f
MV
300/* Print the name of a symbol. */
301
302void
303scm_print_symbol_name (const char *str, size_t len, SCM port)
304{
c6b49e89
MV
305 /* This points to the first character that has not yet been written to the
306 * port. */
307 size_t pos = 0;
308 /* This points to the character we're currently looking at. */
6662998f 309 size_t end;
c6b49e89
MV
310 /* If the name contains weird characters, we'll escape them with
311 * backslashes and set this flag; it indicates that we should surround the
312 * name with "#{" and "}#". */
313 int weird = 0;
314 /* Backslashes are not sufficient to make a name weird, but if a name is
315 * weird because of other characters, backslahes need to be escaped too.
316 * The first time we see a backslash, we set maybe_weird, and mw_pos points
317 * to the backslash. Then if the name turns out to be weird, we re-process
318 * everything starting from mw_pos. */
319 int maybe_weird = 0;
6662998f 320 size_t mw_pos = 0;
c6b49e89
MV
321 /* If the name is purely numeric, then it's weird as a whole, even though
322 * none of the individual characters is weird. But we won't know this
323 * until we reach the end of the name. This flag describes the part of the
324 * name we've looked at so far. */
325 int all_digits = 1;
6662998f 326
c6b49e89 327 if (len == 0 || str[0] == '\'' || str[0] == ':' || str[len-1] == ':')
6662998f
MV
328 {
329 scm_lfwrite ("#{", 2, port);
330 weird = 1;
331 }
c6b49e89 332
6662998f
MV
333 for (end = pos; end < len; ++end)
334 switch (str[end])
335 {
336#ifdef BRACKETS_AS_PARENS
337 case '[':
338 case ']':
339#endif
340 case '(':
341 case ')':
342 case '"':
343 case ';':
c6b49e89 344 case '#':
6662998f
MV
345 case SCM_WHITE_SPACES:
346 case SCM_LINE_INCREMENTORS:
c6b49e89 347 all_digits = 0;
6662998f
MV
348 weird_handler:
349 if (maybe_weird)
350 {
351 end = mw_pos;
352 maybe_weird = 0;
353 }
354 if (!weird)
355 {
356 scm_lfwrite ("#{", 2, port);
357 weird = 1;
358 }
359 if (pos < end)
c6b49e89 360 scm_lfwrite (str + pos, end - pos, port);
6662998f
MV
361 {
362 char buf[2];
363 buf[0] = '\\';
364 buf[1] = str[end];
365 scm_lfwrite (buf, 2, port);
366 }
367 pos = end + 1;
368 break;
369 case '\\':
c6b49e89 370 all_digits = 0;
6662998f
MV
371 if (weird)
372 goto weird_handler;
373 if (!maybe_weird)
374 {
375 maybe_weird = 1;
376 mw_pos = pos;
377 }
378 break;
c6b49e89
MV
379 case '0': case '1': case '2': case '3': case '4':
380 case '5': case '6': case '7': case '8': case '9':
6662998f
MV
381 break;
382 default:
c6b49e89 383 all_digits = 0;
6662998f
MV
384 break;
385 }
c6b49e89
MV
386 if (all_digits)
387 {
388 scm_lfwrite ("#{", 2, port);
389 weird = 1;
390 }
6662998f
MV
391 if (pos < end)
392 scm_lfwrite (str + pos, end - pos, port);
393 if (weird)
394 scm_lfwrite ("}#", 2, port);
395}
396
c62fbfe1 397/* Print generally. Handles both write and display according to PSTATE.
0f2d19dd 398 */
8b840115
MD
399SCM_GPROC(s_write, "write", 1, 1, 0, scm_write, g_write);
400SCM_GPROC(s_display, "display", 1, 1, 0, scm_display, g_display);
1cc91f1b 401
0f2d19dd 402void
1bbd0b84 403scm_iprin1 (SCM exp, SCM port, scm_print_state *pstate)
0f2d19dd 404{
54778cd3 405 switch (SCM_ITAG3 (exp))
0f2d19dd 406 {
e34f941a
DH
407 case scm_tc3_closure:
408 case scm_tc3_tc7_1:
409 case scm_tc3_tc7_2:
410 /* These tc3 tags should never occur in an immediate value. They are
411 * only used in cell types of non-immediates, i. e. the value returned
412 * by SCM_CELL_TYPE (exp) can use these tags.
413 */
414 scm_ipruk ("immediate", exp, port);
415 break;
416 case scm_tc3_int_1:
417 case scm_tc3_int_2:
0f2d19dd
JB
418 scm_intprint (SCM_INUM (exp), 10, port);
419 break;
e34f941a 420 case scm_tc3_imm24:
7866a09b 421 if (SCM_CHARP (exp))
0f2d19dd 422 {
e34f941a 423 long i = SCM_CHAR (exp);
5ca6dc39 424
b7f3516f
TT
425 if (SCM_WRITINGP (pstate))
426 {
427 scm_puts ("#\\", port);
428 if ((i >= 0) && (i <= ' ') && scm_charnames[i])
429 scm_puts (scm_charnames[i], port);
57b74422
GH
430#ifndef EBCDIC
431 else if (i == '\177')
432 scm_puts (scm_charnames[scm_n_charnames - 1], port);
433#endif
b7f3516f
TT
434 else if (i < 0 || i > '\177')
435 scm_intprint (i, 8, port);
436 else
437 scm_putc (i, port);
438 }
439 else
440 scm_putc (i, port);
0f2d19dd 441 }
a51ea417 442 else if (SCM_IFLAGP (exp)
e17d318f
DH
443 && ((size_t) SCM_IFLAGNUM (exp) < (sizeof iflagnames / sizeof (char *))))
444 {
445 scm_puts (iflagnames [SCM_IFLAGNUM (exp)], port);
446 }
447 else if (SCM_ISYMP (exp)
5ca6dc39 448 && ((size_t) SCM_ISYMNUM (exp) < (sizeof scm_isymnames / sizeof (char *))))
e17d318f 449 {
b7f3516f 450 scm_puts (SCM_ISYMCHARS (exp), port);
e17d318f 451 }
0f2d19dd
JB
452 else if (SCM_ILOCP (exp))
453 {
b7f3516f 454 scm_puts ("#@", port);
1be6b49c 455 scm_intprint ((long) SCM_IFRAME (exp), 10, port);
b7f3516f 456 scm_putc (SCM_ICDRP (exp) ? '-' : '+', port);
1be6b49c 457 scm_intprint ((long) SCM_IDIST (exp), 10, port);
0f2d19dd
JB
458 }
459 else
e34f941a
DH
460 {
461 /* unknown immediate value */
462 scm_ipruk ("immediate", exp, port);
463 }
0f2d19dd 464 break;
e34f941a 465 case scm_tc3_cons:
0f2d19dd
JB
466 switch (SCM_TYP7 (exp))
467 {
904a077d
MV
468 case scm_tcs_struct:
469 {
470 ENTER_NESTED_DATA (pstate, exp, circref);
471 if (SCM_OBJ_CLASS_FLAGS (exp) & SCM_CLASSF_GOOPS)
472 {
473 SCM pwps, print = pstate->writingp ? g_write : g_display;
474 if (!print)
475 goto print_struct;
dfd03fb9 476 pwps = scm_i_port_with_print_state (port, pstate->handle);
7663c008 477 pstate->revealed = 1;
904a077d
MV
478 scm_call_generic_2 (print, exp, pwps);
479 }
480 else
481 {
482 print_struct:
483 scm_print_struct (exp, port, pstate);
484 }
485 EXIT_NESTED_DATA (pstate);
486 }
487 break;
0f2d19dd
JB
488 case scm_tcs_cons_imcar:
489 case scm_tcs_cons_nimcar:
c62fbfe1
MD
490 ENTER_NESTED_DATA (pstate, exp, circref);
491 scm_iprlist ("(", exp, ')', port, pstate);
492 EXIT_NESTED_DATA (pstate);
a51ea417
MD
493 break;
494 circref:
c62fbfe1 495 print_circref (port, pstate, exp);
0f2d19dd
JB
496 break;
497 case scm_tcs_closures:
bb35f315
MV
498 if (SCM_FALSEP (scm_procedure_p (SCM_PRINT_CLOSURE))
499 || SCM_FALSEP (scm_printer_apply (SCM_PRINT_CLOSURE,
77c25af7 500 exp, port, pstate)))
726d810a
DH
501 {
502 SCM formals = SCM_CLOSURE_FORMALS (exp);
503 scm_puts ("#<procedure", port);
504 scm_putc (' ', port);
505 scm_iprin1 (scm_procedure_name (exp), port, pstate);
506 scm_putc (' ', port);
507 if (SCM_PRINT_SOURCE_P)
508 {
509 SCM env = SCM_ENV (exp);
510 SCM xenv = SCM_EXTEND_ENV (formals, SCM_EOL, env);
511 SCM src = scm_unmemocopy (SCM_CODE (exp), xenv);
512 ENTER_NESTED_DATA (pstate, exp, circref);
513 scm_iprin1 (src, port, pstate);
514 EXIT_NESTED_DATA (pstate);
515 }
516 else
517 scm_iprin1 (formals, port, pstate);
b7f3516f 518 scm_putc ('>', port);
726d810a 519 }
0f2d19dd 520 break;
534c55a9
DH
521 case scm_tc7_number:
522 switch SCM_TYP16 (exp) {
523 case scm_tc16_big:
524 scm_bigprint (exp, port, pstate);
525 break;
526 case scm_tc16_real:
527 scm_print_real (exp, port, pstate);
528 break;
529 case scm_tc16_complex:
530 scm_print_complex (exp, port, pstate);
531 break;
f92e85f7
MV
532 case scm_tc16_fraction:
533 scm_i_print_fraction (exp, port, pstate);
534 break;
534c55a9
DH
535 }
536 break;
0f2d19dd 537 case scm_tc7_string:
c62fbfe1 538 if (SCM_WRITINGP (pstate))
0f2d19dd 539 {
1be6b49c 540 size_t i;
5ca6dc39 541
b7f3516f 542 scm_putc ('"', port);
d1ca2c64 543 for (i = 0; i < SCM_STRING_LENGTH (exp); ++i)
fea8e142
MV
544 {
545 unsigned char ch = SCM_STRING_CHARS (exp)[i];
546 if ((ch < 32 && ch != '\n') || (127 <= ch && ch < 148))
547 {
548 static char const hex[]="0123456789abcdef";
549 scm_putc ('\\', port);
550 scm_putc ('x', port);
551 scm_putc (hex [ch / 16], port);
552 scm_putc (hex [ch % 16], port);
553 }
554 else
555 {
556 if (ch == '"' || ch == '\\')
557 scm_putc ('\\', port);
558 scm_putc (ch, port);
559 }
560 }
b7f3516f 561 scm_putc ('"', port);
0f2d19dd
JB
562 }
563 else
fea8e142
MV
564 scm_lfwrite (SCM_STRING_CHARS (exp), SCM_STRING_LENGTH (exp),
565 port);
0f2d19dd 566 break;
28b06554 567 case scm_tc7_symbol:
9ff28a13
MV
568 if (SCM_SYMBOL_INTERNED_P (exp))
569 {
570 scm_print_symbol_name (SCM_SYMBOL_CHARS (exp),
571 SCM_SYMBOL_LENGTH (exp),
572 port);
573 scm_remember_upto_here_1 (exp);
574 }
575 else
576 {
577 scm_puts ("#<uninterned-symbol ", port);
578 scm_print_symbol_name (SCM_SYMBOL_CHARS (exp),
579 SCM_SYMBOL_LENGTH (exp),
580 port);
581 scm_putc (' ', port);
582 scm_intprint ((long)exp, 16, port);
583 scm_putc ('>', port);
584 }
6662998f 585 break;
e5aca4b5
MV
586 case scm_tc7_variable:
587 scm_i_variable_print (exp, port, pstate);
588 break;
0f2d19dd 589 case scm_tc7_wvect:
c62fbfe1 590 ENTER_NESTED_DATA (pstate, exp, circref);
0f2d19dd 591 if (SCM_IS_WHVEC (exp))
b7f3516f 592 scm_puts ("#wh(", port);
0f2d19dd 593 else
b7f3516f 594 scm_puts ("#w(", port);
0f2d19dd
JB
595 goto common_vector_printer;
596
597 case scm_tc7_vector:
c62fbfe1 598 ENTER_NESTED_DATA (pstate, exp, circref);
b7f3516f 599 scm_puts ("#(", port);
0f2d19dd 600 common_vector_printer:
9fbaf27c 601 {
c014a02e
ML
602 register long i;
603 long last = SCM_VECTOR_LENGTH (exp) - 1;
9fbaf27c 604 int cutp = 0;
b17004b8 605 if (pstate->fancyp && SCM_VECTOR_LENGTH (exp) > pstate->length)
9fbaf27c
MD
606 {
607 last = pstate->length - 1;
608 cutp = 1;
609 }
610 for (i = 0; i < last; ++i)
611 {
612 /* CHECK_INTS; */
613 scm_iprin1 (SCM_VELTS (exp)[i], port, pstate);
b7f3516f 614 scm_putc (' ', port);
9fbaf27c
MD
615 }
616 if (i == last)
617 {
618 /* CHECK_INTS; */
619 scm_iprin1 (SCM_VELTS (exp)[i], port, pstate);
620 }
621 if (cutp)
b7f3516f
TT
622 scm_puts (" ...", port);
623 scm_putc (')', port);
9fbaf27c 624 }
c62fbfe1 625 EXIT_NESTED_DATA (pstate);
0f2d19dd 626 break;
5f4df973 627#if SCM_HAVE_ARRAYS
0f2d19dd
JB
628 case scm_tc7_bvect:
629 case scm_tc7_byvect:
630 case scm_tc7_svect:
631 case scm_tc7_ivect:
632 case scm_tc7_uvect:
633 case scm_tc7_fvect:
634 case scm_tc7_dvect:
635 case scm_tc7_cvect:
ffbda747 636#if SCM_SIZEOF_LONG_LONG != 0
0f2d19dd
JB
637 case scm_tc7_llvect:
638#endif
c62fbfe1 639 scm_raprin1 (exp, port, pstate);
0f2d19dd 640 break;
afe5177e 641#endif
0f2d19dd 642 case scm_tcs_subrs:
f76af603 643 scm_puts (SCM_SUBR_GENERIC (exp)
9de33deb
MD
644 ? "#<primitive-generic "
645 : "#<primitive-procedure ",
646 port);
a002f1a2 647 scm_puts (SCM_SYMBOL_CHARS (SCM_SNAME (exp)), port);
b7f3516f 648 scm_putc ('>', port);
0f2d19dd
JB
649 break;
650#ifdef CCLO
651 case scm_tc7_cclo:
56977059
MD
652 {
653 SCM proc = SCM_CCLO_SUBR (exp);
54778cd3 654 if (SCM_EQ_P (proc, scm_f_gsubr_apply))
56977059
MD
655 {
656 /* Print gsubrs as primitives */
c180dfd3 657 SCM name = scm_procedure_name (exp);
56977059 658 scm_puts ("#<primitive-procedure", port);
d5cf5324 659 if (!SCM_FALSEP (name))
56977059
MD
660 {
661 scm_putc (' ', port);
a002f1a2 662 scm_puts (SCM_SYMBOL_CHARS (name), port);
56977059
MD
663 }
664 }
665 else
666 {
667 scm_puts ("#<compiled-closure ", port);
668 scm_iprin1 (proc, port, pstate);
669 }
670 scm_putc ('>', port);
671 }
0f2d19dd
JB
672 break;
673#endif
c180dfd3
MD
674 case scm_tc7_pws:
675 scm_puts ("#<procedure-with-setter", port);
676 {
677 SCM name = scm_procedure_name (exp);
d5cf5324 678 if (!SCM_FALSEP (name))
c180dfd3
MD
679 {
680 scm_putc (' ', port);
b24b5e13 681 scm_display (name, port);
c180dfd3
MD
682 }
683 }
684 scm_putc ('>', port);
685 break;
0f2d19dd 686 case scm_tc7_port:
5ca6dc39
JB
687 {
688 register long i = SCM_PTOBNUM (exp);
689 if (i < scm_numptob
690 && scm_ptobs[i].print
691 && (scm_ptobs[i].print) (exp, port, pstate))
a51ea417 692 break;
5ca6dc39
JB
693 goto punk;
694 }
695 case scm_tc7_smob:
7a7f7c53
DH
696 ENTER_NESTED_DATA (pstate, exp, circref);
697 SCM_SMOB_DESCRIPTOR (exp).print (exp, port, pstate);
698 EXIT_NESTED_DATA (pstate);
699 break;
0f2d19dd 700 default:
a51ea417
MD
701 punk:
702 scm_ipruk ("type", exp, port);
0f2d19dd
JB
703 }
704 }
705}
706
c62fbfe1
MD
707/* Print states are necessary for circular reference safe printing.
708 * They are also expensive to allocate. Therefore print states are
709 * kept in a pool so that they can be reused.
710 */
1cc91f1b 711
bb35f315
MV
712/* The PORT argument can also be a print-state/port pair, which will
713 * then be used instead of allocating a new print state. This is
714 * useful for continuing a chain of print calls from Scheme. */
715
a51ea417 716void
1bbd0b84 717scm_prin1 (SCM exp, SCM port, int writingp)
a51ea417 718{
c4f37e80
MV
719 SCM handle = SCM_BOOL_F; /* Will GC protect the handle whilst unlinked */
720 SCM pstate_scm;
c62fbfe1 721 scm_print_state *pstate;
15635be5 722 int old_writingp;
c62fbfe1 723
bb35f315
MV
724 /* If PORT is a print-state/port pair, use that. Else create a new
725 print-state. */
c4f37e80 726
0c95b57d 727 if (SCM_PORT_WITH_PS_P (port))
bb35f315 728 {
52235e71
MD
729 pstate_scm = SCM_PORT_WITH_PS_PS (port);
730 port = SCM_PORT_WITH_PS_PORT (port);
bb35f315
MV
731 }
732 else
c62fbfe1 733 {
c4f37e80 734 /* First try to allocate a print state from the pool */
dfd03fb9 735 scm_i_plugin_mutex_lock (&print_state_mutex);
d5cf5324 736 if (!SCM_NULLP (print_state_pool))
c4f37e80 737 {
d5cf5324
DH
738 handle = print_state_pool;
739 print_state_pool = SCM_CDR (print_state_pool);
c4f37e80 740 }
dfd03fb9 741 scm_i_plugin_mutex_unlock (&print_state_mutex);
54778cd3 742 if (SCM_FALSEP (handle))
d5cf5324 743 handle = scm_list_1 (make_print_state ());
c4f37e80 744 pstate_scm = SCM_CAR (handle);
c62fbfe1 745 }
c62fbfe1 746
c4f37e80 747 pstate = SCM_PRINT_STATE (pstate_scm);
15635be5 748 old_writingp = pstate->writingp;
c62fbfe1
MD
749 pstate->writingp = writingp;
750 scm_iprin1 (exp, port, pstate);
15635be5 751 pstate->writingp = old_writingp;
c62fbfe1 752
bb35f315
MV
753 /* Return print state to pool if it has been created above and
754 hasn't escaped to Scheme. */
755
54778cd3 756 if (!SCM_FALSEP (handle) && !pstate->revealed)
c4f37e80 757 {
dfd03fb9 758 scm_i_plugin_mutex_lock (&print_state_mutex);
d5cf5324
DH
759 SCM_SETCDR (handle, print_state_pool);
760 print_state_pool = handle;
dfd03fb9 761 scm_i_plugin_mutex_unlock (&print_state_mutex);
c4f37e80 762 }
a51ea417
MD
763}
764
0f2d19dd
JB
765
766/* Print an integer.
767 */
1cc91f1b 768
0f2d19dd 769void
1bbd0b84 770scm_intprint (long n, int radix, SCM port)
0f2d19dd
JB
771{
772 char num_buf[SCM_INTBUFLEN];
b7f3516f 773 scm_lfwrite (num_buf, scm_iint2str (n, radix, num_buf), port);
0f2d19dd
JB
774}
775
776/* Print an object of unrecognized type.
777 */
1cc91f1b 778
0f2d19dd 779void
1bbd0b84 780scm_ipruk (char *hdr, SCM ptr, SCM port)
0f2d19dd 781{
b7f3516f
TT
782 scm_puts ("#<unknown-", port);
783 scm_puts (hdr, port);
c8a1bdc4 784 if (scm_in_heap_p (ptr))
0f2d19dd 785 {
b7f3516f 786 scm_puts (" (0x", port);
54778cd3 787 scm_intprint (SCM_CELL_WORD_0 (ptr), 16, port);
b7f3516f 788 scm_puts (" . 0x", port);
54778cd3 789 scm_intprint (SCM_CELL_WORD_1 (ptr), 16, port);
b7f3516f 790 scm_puts (") @", port);
0f2d19dd 791 }
b7f3516f 792 scm_puts (" 0x", port);
54778cd3 793 scm_intprint (SCM_UNPACK (ptr), 16, port);
b7f3516f 794 scm_putc ('>', port);
0f2d19dd
JB
795}
796
1cc91f1b 797
904a077d 798/* Print a list.
22a52da1 799 */
0f2d19dd 800void
34d19ef6 801scm_iprlist (char *hdr, SCM exp, int tlr, SCM port, scm_print_state *pstate)
0f2d19dd 802{
c62fbfe1 803 register SCM hare, tortoise;
c014a02e 804 long floor = pstate->top - 2;
b7f3516f 805 scm_puts (hdr, port);
0f2d19dd 806 /* CHECK_INTS; */
c62fbfe1
MD
807 if (pstate->fancyp)
808 goto fancy_printing;
809
810 /* Run a hare and tortoise so that total time complexity will be
811 O(depth * N) instead of O(N^2). */
812 hare = SCM_CDR (exp);
813 tortoise = exp;
904a077d 814 while (SCM_CONSP (hare))
c62fbfe1 815 {
54778cd3 816 if (SCM_EQ_P (hare, tortoise))
c62fbfe1
MD
817 goto fancy_printing;
818 hare = SCM_CDR (hare);
d5cf5324 819 if (!SCM_CONSP (hare))
c62fbfe1
MD
820 break;
821 hare = SCM_CDR (hare);
822 tortoise = SCM_CDR (tortoise);
823 }
824
825 /* No cdr cycles intrinsic to this list */
826 scm_iprin1 (SCM_CAR (exp), port, pstate);
904a077d 827 for (exp = SCM_CDR (exp); SCM_CONSP (exp); exp = SCM_CDR (exp))
0f2d19dd 828 {
c014a02e 829 register long i;
5ca6dc39 830
c62fbfe1 831 for (i = floor; i >= 0; --i)
230d095f 832 if (SCM_EQ_P (pstate->ref_stack[i], exp))
c62fbfe1
MD
833 goto circref;
834 PUSH_REF (pstate, exp);
b7f3516f 835 scm_putc (' ', port);
0f2d19dd 836 /* CHECK_INTS; */
c62fbfe1 837 scm_iprin1 (SCM_CAR (exp), port, pstate);
0f2d19dd 838 }
c96d76b8 839 if (!SCM_NULL_OR_NIL_P (exp))
0f2d19dd 840 {
b7f3516f 841 scm_puts (" . ", port);
c62fbfe1 842 scm_iprin1 (exp, port, pstate);
0f2d19dd 843 }
c62fbfe1 844
a51ea417 845end:
b7f3516f 846 scm_putc (tlr, port);
c62fbfe1 847 pstate->top = floor + 2;
a51ea417 848 return;
c62fbfe1
MD
849
850fancy_printing:
851 {
c014a02e 852 long n = pstate->length;
c62fbfe1
MD
853
854 scm_iprin1 (SCM_CAR (exp), port, pstate);
855 exp = SCM_CDR (exp); --n;
904a077d 856 for (; SCM_CONSP (exp); exp = SCM_CDR (exp))
c62fbfe1 857 {
c014a02e 858 register unsigned long i;
5ca6dc39 859
c62fbfe1 860 for (i = 0; i < pstate->top; ++i)
230d095f 861 if (SCM_EQ_P (pstate->ref_stack[i], exp))
c62fbfe1
MD
862 goto fancy_circref;
863 if (pstate->fancyp)
864 {
865 if (n == 0)
866 {
b7f3516f 867 scm_puts (" ...", port);
c62fbfe1
MD
868 goto skip_tail;
869 }
870 else
871 --n;
872 }
873 PUSH_REF(pstate, exp);
874 ++pstate->list_offset;
b7f3516f 875 scm_putc (' ', port);
c62fbfe1
MD
876 /* CHECK_INTS; */
877 scm_iprin1 (SCM_CAR (exp), port, pstate);
878 }
879 }
c96d76b8 880 if (!SCM_NULL_OR_NIL_P (exp))
c62fbfe1 881 {
b7f3516f 882 scm_puts (" . ", port);
c62fbfe1
MD
883 scm_iprin1 (exp, port, pstate);
884 }
885skip_tail:
886 pstate->list_offset -= pstate->top - floor - 2;
a51ea417 887 goto end;
a51ea417 888
c62fbfe1
MD
889fancy_circref:
890 pstate->list_offset -= pstate->top - floor - 2;
891
892circref:
b7f3516f 893 scm_puts (" . ", port);
c62fbfe1
MD
894 print_circref (port, pstate, exp);
895 goto end;
0f2d19dd
JB
896}
897
898\f
899
bb35f315
MV
900int
901scm_valid_oport_value_p (SCM val)
902{
368cf54d
GB
903 return (SCM_OPOUTPORTP (val)
904 || (SCM_PORT_WITH_PS_P (val)
905 && SCM_OPOUTPORTP (SCM_PORT_WITH_PS_PORT (val))));
bb35f315
MV
906}
907
8b840115 908/* SCM_GPROC(s_write, "write", 1, 1, 0, scm_write, g_write); */
1cc91f1b 909
0f2d19dd 910SCM
1bbd0b84 911scm_write (SCM obj, SCM port)
0f2d19dd
JB
912{
913 if (SCM_UNBNDP (port))
914 port = scm_cur_outp;
3eb7e6ee
JB
915
916 SCM_ASSERT (scm_valid_oport_value_p (port), port, SCM_ARG2, s_write);
bb35f315 917
a51ea417 918 scm_prin1 (obj, port, 1);
0f2d19dd
JB
919#ifdef HAVE_PIPE
920# ifdef EPIPE
921 if (EPIPE == errno)
922 scm_close_port (port);
923# endif
924#endif
925 return SCM_UNSPECIFIED;
926}
927
928
8b840115 929/* SCM_GPROC(s_display, "display", 1, 1, 0, scm_display, g_display); */
1cc91f1b 930
0f2d19dd 931SCM
1bbd0b84 932scm_display (SCM obj, SCM port)
0f2d19dd
JB
933{
934 if (SCM_UNBNDP (port))
935 port = scm_cur_outp;
3eb7e6ee
JB
936
937 SCM_ASSERT (scm_valid_oport_value_p (port), port, SCM_ARG2, s_display);
bb35f315 938
a51ea417 939 scm_prin1 (obj, port, 0);
0f2d19dd
JB
940#ifdef HAVE_PIPE
941# ifdef EPIPE
942 if (EPIPE == errno)
943 scm_close_port (port);
944# endif
945#endif
946 return SCM_UNSPECIFIED;
947}
948
70d63753
GB
949
950SCM_DEFINE (scm_simple_format, "simple-format", 2, 0, 1,
951 (SCM destination, SCM message, SCM args),
eca65e90
MG
952 "Write @var{message} to @var{destination}, defaulting to\n"
953 "the current output port.\n"
954 "@var{message} can contain @code{~A} (was @code{%s}) and\n"
955 "@code{~S} (was @code{%S}) escapes. When printed,\n"
956 "the escapes are replaced with corresponding members of\n"
957 "@var{ARGS}:\n"
958 "@code{~A} formats using @code{display} and @code{~S} formats\n"
959 "using @code{write}.\n"
960 "If @var{destination} is @code{#t}, then use the current output\n"
961 "port, if @var{destination} is @code{#f}, then return a string\n"
962 "containing the formatted text. Does not add a trailing newline.")
70d63753
GB
963#define FUNC_NAME s_scm_simple_format
964{
dfd03fb9 965 SCM port, answer = SCM_UNSPECIFIED;
70d63753
GB
966 int fReturnString = 0;
967 int writingp;
968 char *start;
b24b5e13 969 char *end;
70d63753
GB
970 char *p;
971
daba1a71
MD
972 if (SCM_EQ_P (destination, SCM_BOOL_T))
973 {
dfd03fb9 974 destination = port = scm_cur_outp;
daba1a71
MD
975 }
976 else if (SCM_FALSEP (destination))
977 {
978 fReturnString = 1;
dfd03fb9
MD
979 port = scm_mkstrport (SCM_INUM0,
980 scm_make_string (SCM_INUM0, SCM_UNDEFINED),
981 SCM_OPN | SCM_WRTNG,
982 FUNC_NAME);
983 destination = port;
daba1a71
MD
984 }
985 else
986 {
987 SCM_VALIDATE_OPORT_VALUE (1, destination);
dfd03fb9 988 port = SCM_COERCE_OUTPORT (destination);
daba1a71
MD
989 }
990 SCM_VALIDATE_STRING (2, message);
af45e3b0 991 SCM_VALIDATE_REST_ARGUMENT (args);
70d63753 992
34f0f2b8 993 start = SCM_STRING_CHARS (message);
b24b5e13
DH
994 end = start + SCM_STRING_LENGTH (message);
995 for (p = start; p != end; ++p)
70d63753
GB
996 if (*p == '~')
997 {
b24b5e13 998 if (++p == end)
6662998f
MV
999 break;
1000
1001 switch (*p)
1002 {
1003 case 'A': case 'a':
1004 writingp = 0;
1005 break;
1006 case 'S': case 's':
1007 writingp = 1;
1008 break;
1009 case '~':
dfd03fb9 1010 scm_lfwrite (start, p - start, port);
6662998f
MV
1011 start = p + 1;
1012 continue;
1013 case '%':
dfd03fb9
MD
1014 scm_lfwrite (start, p - start - 1, port);
1015 scm_newline (port);
6662998f
MV
1016 start = p + 1;
1017 continue;
1018 default:
1afff620
KN
1019 SCM_MISC_ERROR ("FORMAT: Unsupported format option ~~~A - use (ice-9 format) instead",
1020 scm_list_1 (SCM_MAKE_CHAR (*p)));
6662998f
MV
1021
1022 }
70d63753 1023
6662998f
MV
1024
1025 if (!SCM_CONSP (args))
1afff620
KN
1026 SCM_MISC_ERROR ("FORMAT: Missing argument for ~~~A",
1027 scm_list_1 (SCM_MAKE_CHAR (*p)));
6662998f 1028
dfd03fb9
MD
1029 scm_lfwrite (start, p - start - 1, port);
1030 /* we pass destination here */
70d63753
GB
1031 scm_prin1 (SCM_CAR (args), destination, writingp);
1032 args = SCM_CDR (args);
1033 start = p + 1;
1034 }
6662998f 1035
dfd03fb9 1036 scm_lfwrite (start, p - start, port);
d5cf5324 1037 if (!SCM_EQ_P (args, SCM_EOL))
1afff620
KN
1038 SCM_MISC_ERROR ("FORMAT: ~A superfluous arguments",
1039 scm_list_1 (scm_length (args)));
70d63753
GB
1040
1041 if (fReturnString)
1042 answer = scm_strport_to_string (destination);
1043
daba1a71 1044 return scm_return_first (answer, message);
70d63753
GB
1045}
1046#undef FUNC_NAME
1047
1048
3b3b36dd 1049SCM_DEFINE (scm_newline, "newline", 0, 1, 0,
b450f070 1050 (SCM port),
8f85c0c6
NJ
1051 "Send a newline to @var{port}.\n"
1052 "If @var{port} is omitted, send to the current output port.")
1bbd0b84 1053#define FUNC_NAME s_scm_newline
0f2d19dd
JB
1054{
1055 if (SCM_UNBNDP (port))
bb35f315 1056 port = scm_cur_outp;
3eb7e6ee 1057
34d19ef6 1058 SCM_VALIDATE_OPORT_VALUE (1, port);
bb35f315 1059
0ef4ae82 1060 scm_putc ('\n', SCM_COERCE_OUTPORT (port));
0f2d19dd
JB
1061 return SCM_UNSPECIFIED;
1062}
1bbd0b84 1063#undef FUNC_NAME
0f2d19dd 1064
3b3b36dd 1065SCM_DEFINE (scm_write_char, "write-char", 1, 1, 0,
b450f070 1066 (SCM chr, SCM port),
eca65e90 1067 "Send character @var{chr} to @var{port}.")
1bbd0b84 1068#define FUNC_NAME s_scm_write_char
0f2d19dd
JB
1069{
1070 if (SCM_UNBNDP (port))
bb35f315 1071 port = scm_cur_outp;
3eb7e6ee 1072
34d19ef6
HWN
1073 SCM_VALIDATE_CHAR (1, chr);
1074 SCM_VALIDATE_OPORT_VALUE (2, port);
bb35f315 1075
7866a09b 1076 scm_putc ((int) SCM_CHAR (chr), SCM_COERCE_OUTPORT (port));
0f2d19dd
JB
1077#ifdef HAVE_PIPE
1078# ifdef EPIPE
1079 if (EPIPE == errno)
1080 scm_close_port (port);
1081# endif
1082#endif
1083 return SCM_UNSPECIFIED;
1084}
1bbd0b84 1085#undef FUNC_NAME
0f2d19dd 1086
0f2d19dd
JB
1087\f
1088
bb35f315 1089/* Call back to Scheme code to do the printing of special objects
c19bc088
MD
1090 * (like structs). SCM_PRINTER_APPLY applies PROC to EXP and a smob
1091 * containing PORT and PSTATE. This object can be used as the port for
1092 * display/write etc to continue the current print chain. The REVEALED
1093 * field of PSTATE is set to true to indicate that the print state has
1094 * escaped to Scheme and thus has to be freed by the GC.
1095 */
1096
92c2555f 1097scm_t_bits scm_tc16_port_with_ps;
c19bc088
MD
1098
1099/* Print exactly as the port itself would */
1100
1101static int
e841c3e0 1102port_with_ps_print (SCM obj, SCM port, scm_print_state *pstate)
c19bc088
MD
1103{
1104 obj = SCM_PORT_WITH_PS_PORT (obj);
1105 return scm_ptobs[SCM_PTOBNUM (obj)].print (obj, port, pstate);
1106}
c4f37e80
MV
1107
1108SCM
1bbd0b84 1109scm_printer_apply (SCM proc, SCM exp, SCM port, scm_print_state *pstate)
c4f37e80 1110{
bb35f315 1111 pstate->revealed = 1;
dfd03fb9
MD
1112 return scm_call_2 (proc, exp,
1113 scm_i_port_with_print_state (port, pstate->handle));
c19bc088
MD
1114}
1115
dfd03fb9 1116SCM_DEFINE (scm_port_with_print_state, "port-with-print-state", 1, 1, 0,
1bbd0b84 1117 (SCM port, SCM pstate),
71331188 1118 "Create a new port which behaves like @var{port}, but with an\n"
dfd03fb9
MD
1119 "included print state @var{pstate}. @var{pstate} is optional.\n"
1120 "If @var{pstate} isn't supplied and @var{port} already has\n"
1121 "a print state, the old print state is reused.")
1bbd0b84 1122#define FUNC_NAME s_scm_port_with_print_state
c19bc088 1123{
34d19ef6 1124 SCM_VALIDATE_OPORT_VALUE (1, port);
dfd03fb9
MD
1125 if (!SCM_UNBNDP (pstate))
1126 SCM_VALIDATE_PRINTSTATE (2, pstate);
1127 return scm_i_port_with_print_state (port, pstate);
c19bc088 1128}
1bbd0b84 1129#undef FUNC_NAME
c19bc088 1130
a1ec6916 1131SCM_DEFINE (scm_get_print_state, "get-print-state", 1, 0, 0,
1bbd0b84 1132 (SCM port),
71331188
MG
1133 "Return the print state of the port @var{port}. If @var{port}\n"
1134 "has no associated print state, @code{#f} is returned.")
1bbd0b84 1135#define FUNC_NAME s_scm_get_print_state
c19bc088 1136{
368cf54d
GB
1137 if (SCM_PORT_WITH_PS_P (port))
1138 return SCM_PORT_WITH_PS_PS (port);
f5f2dcff 1139 if (SCM_OUTPUT_PORT_P (port))
368cf54d 1140 return SCM_BOOL_F;
276dd677 1141 SCM_WRONG_TYPE_ARG (1, port);
c4f37e80 1142}
1bbd0b84 1143#undef FUNC_NAME
bb35f315 1144
c4f37e80 1145\f
1cc91f1b 1146
0f2d19dd
JB
1147void
1148scm_init_print ()
0f2d19dd 1149{
c19bc088 1150 SCM vtable, layout, type;
d5cf5324 1151
b7ff98dd 1152 scm_init_opts (scm_print_options, scm_print_opts, SCM_N_PRINT_OPTIONS);
d5cf5324
DH
1153
1154 scm_gc_register_root (&print_state_pool);
1155 scm_gc_register_root (&scm_print_state_vtable);
3ce4544c 1156 vtable = scm_make_vtable_vtable (scm_nullstr, SCM_INUM0, SCM_EOL);
4bfdf158 1157 layout = scm_make_struct_layout (scm_makfrom0str (SCM_PRINT_STATE_LAYOUT));
1afff620 1158 type = scm_make_struct (vtable, SCM_INUM0, scm_list_1 (layout));
38ae064c 1159 scm_set_struct_vtable_name_x (type, scm_str2symbol ("print-state"));
bb35f315 1160 scm_print_state_vtable = type;
c4f37e80 1161
c19bc088
MD
1162 /* Don't want to bind a wrapper class in GOOPS, so pass 0 as arg1. */
1163 scm_tc16_port_with_ps = scm_make_smob_type (0, 0);
1164 scm_set_smob_mark (scm_tc16_port_with_ps, scm_markcdr);
e841c3e0 1165 scm_set_smob_print (scm_tc16_port_with_ps, port_with_ps_print);
c19bc088 1166
a0599745 1167#include "libguile/print.x"
0f2d19dd 1168}
89e00824
ML
1169
1170/*
1171 Local Variables:
1172 c-file-style: "gnu"
1173 End:
1174*/