*** empty log message ***
[bpt/guile.git] / libguile / ports.c
CommitLineData
840ae05d 1/* Copyright (C) 1995,1996,1997,1998,1999 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. */
1bbd0b84
GB
41
42/* Software engineering face-lift by Greg J. Badros, 11-Dec-1999,
43 gjb@cs.washington.edu, http://www.cs.washington.edu/homes/gjb */
44
0f2d19dd 45\f
d68fee48
JB
46/* Headers. */
47
0f2d19dd
JB
48#include <stdio.h>
49#include "_scm.h"
f12733c9
MD
50#include "objects.h"
51#include "smob.h"
20e6290e 52#include "chars.h"
0f2d19dd 53
547e65b5 54#include "keywords.h"
20e6290e 55
1bbd0b84 56#include "scm_validate.h"
20e6290e 57#include "ports.h"
0f2d19dd
JB
58
59#ifdef HAVE_MALLOC_H
95b88819 60#include <malloc.h>
0f2d19dd
JB
61#endif
62
63#ifdef HAVE_UNISTD_H
64#include <unistd.h>
65#endif
66
95b88819
GH
67#ifdef HAVE_SYS_IOCTL_H
68#include <sys/ioctl.h>
69#endif
d68fee48 70
0f2d19dd 71\f
d68fee48 72/* The port kind table --- a dynamically resized array of port types. */
0f2d19dd
JB
73
74
75/* scm_ptobs scm_numptob
76 * implement a dynamicly resized array of ptob records.
77 * Indexes into this table are used when generating type
78 * tags for smobjects (if you know a tag you can get an index and conversely).
79 */
f12733c9 80scm_ptob_descriptor *scm_ptobs;
a1c95c45 81int scm_numptob;
0f2d19dd 82
ee149d03 83/* GC marker for a port with stream of SCM type. */
0f2d19dd 84SCM
a284e297 85scm_markstream (SCM ptr)
0f2d19dd
JB
86{
87 int openp;
0f2d19dd 88 openp = SCM_CAR (ptr) & SCM_OPN;
0f2d19dd
JB
89 if (openp)
90 return SCM_STREAM (ptr);
91 else
92 return SCM_BOOL_F;
93}
94
f12733c9 95/*
f12733c9 96 * We choose to use an interface similar to the smob interface with
affc96b5 97 * fill_input and write as standard fields, passed to the port
f12733c9
MD
98 * type constructor, and optional fields set by setters.
99 */
100
101static void flush_void_port (SCM port);
affc96b5 102static void end_input_void_port (SCM port, int offset);
31703ab8 103static void write_void_port (SCM port, void *data, size_t size);
0f2d19dd 104
0f2d19dd 105long
f12733c9 106scm_make_port_type (char *name,
affc96b5
GH
107 int (*fill_input) (SCM port),
108 void (*write) (SCM port, void *data, size_t size))
0f2d19dd
JB
109{
110 char *tmp;
111 if (255 <= scm_numptob)
112 goto ptoberr;
f12733c9
MD
113 SCM_DEFER_INTS;
114 SCM_SYSCALL (tmp = (char *) realloc ((char *) scm_ptobs,
115 (1 + scm_numptob)
116 * sizeof (scm_ptob_descriptor)));
0f2d19dd
JB
117 if (tmp)
118 {
f12733c9 119 scm_ptobs = (scm_ptob_descriptor *) tmp;
affc96b5 120
f12733c9
MD
121 scm_ptobs[scm_numptob].name = name;
122 scm_ptobs[scm_numptob].mark = 0;
123 scm_ptobs[scm_numptob].free = scm_free0;
124 scm_ptobs[scm_numptob].print = scm_port_print;
125 scm_ptobs[scm_numptob].equalp = 0;
affc96b5
GH
126 scm_ptobs[scm_numptob].close = 0;
127
128 scm_ptobs[scm_numptob].write = write;
129 scm_ptobs[scm_numptob].flush = flush_void_port;
130
131 scm_ptobs[scm_numptob].end_input = end_input_void_port;
132 scm_ptobs[scm_numptob].fill_input = fill_input;
133 scm_ptobs[scm_numptob].input_waiting = 0;
134
f12733c9 135 scm_ptobs[scm_numptob].seek = 0;
affc96b5
GH
136 scm_ptobs[scm_numptob].truncate = 0;
137
0f2d19dd
JB
138 scm_numptob++;
139 }
f12733c9 140 SCM_ALLOW_INTS;
0f2d19dd 141 if (!tmp)
f12733c9
MD
142 ptoberr:scm_wta (SCM_MAKINUM ((long) scm_numptob),
143 (char *) SCM_NALLOC, "scm_make_port_type");
144 /* Make a class object if Goops is present */
145 if (scm_port_class)
146 scm_make_port_classes (scm_numptob - 1, SCM_PTOBNAME (scm_numptob - 1));
0f2d19dd
JB
147 return scm_tc7_port + (scm_numptob - 1) * 256;
148}
149
f12733c9 150void
6c747373 151scm_set_port_mark (long tc, SCM (*mark) (SCM))
f12733c9
MD
152{
153 scm_ptobs[SCM_TC2PTOBNUM (tc)].mark = mark;
154}
155
156void
6c747373 157scm_set_port_free (long tc, scm_sizet (*free) (SCM))
f12733c9
MD
158{
159 scm_ptobs[SCM_TC2PTOBNUM (tc)].free = free;
160}
161
162void
6c747373 163scm_set_port_print (long tc, int (*print) (SCM exp, SCM port,
f12733c9
MD
164 scm_print_state *pstate))
165{
166 scm_ptobs[SCM_TC2PTOBNUM (tc)].print = print;
167}
168
169void
6c747373 170scm_set_port_equalp (long tc, SCM (*equalp) (SCM, SCM))
f12733c9
MD
171{
172 scm_ptobs[SCM_TC2PTOBNUM (tc)].equalp = equalp;
173}
174
31703ab8 175void
affc96b5 176scm_set_port_flush (long tc, void (*flush) (SCM port))
31703ab8 177{
affc96b5 178 scm_ptobs[SCM_TC2PTOBNUM (tc)].flush = flush;
31703ab8
GH
179}
180
f12733c9 181void
affc96b5 182scm_set_port_end_input (long tc, void (*end_input) (SCM port, int offset))
f12733c9 183{
affc96b5 184 scm_ptobs[SCM_TC2PTOBNUM (tc)].end_input = end_input;
f12733c9
MD
185}
186
187void
6c747373 188scm_set_port_close (long tc, int (*close) (SCM))
f12733c9 189{
affc96b5 190 scm_ptobs[SCM_TC2PTOBNUM (tc)].close = close;
f12733c9
MD
191}
192
193void
6c747373 194scm_set_port_seek (long tc, off_t (*seek) (SCM port,
f12733c9
MD
195 off_t OFFSET,
196 int WHENCE))
197{
198 scm_ptobs[SCM_TC2PTOBNUM (tc)].seek = seek;
199}
200
201void
6c747373 202scm_set_port_truncate (long tc, void (*truncate) (SCM port, off_t length))
f12733c9 203{
affc96b5 204 scm_ptobs[SCM_TC2PTOBNUM (tc)].truncate = truncate;
f12733c9
MD
205}
206
207void
affc96b5 208scm_set_port_input_waiting (long tc, int (*input_waiting) (SCM))
f12733c9 209{
affc96b5 210 scm_ptobs[SCM_TC2PTOBNUM (tc)].input_waiting = input_waiting;
f12733c9
MD
211}
212
0f2d19dd 213\f
0f2d19dd 214
1bbd0b84
GB
215GUILE_PROC(scm_char_ready_p, "char-ready?", 0, 1, 0,
216 (SCM port),
217"")
218#define FUNC_NAME s_scm_char_ready_p
0f2d19dd 219{
ae4c4016 220 scm_port *pt;
6c951427 221
0f2d19dd
JB
222 if (SCM_UNBNDP (port))
223 port = scm_cur_inp;
224 else
1bbd0b84 225 SCM_VALIDATE_OPINPORT(1,port);
d68fee48 226
ae4c4016
JB
227 pt = SCM_PTAB_ENTRY (port);
228
6c951427
GH
229 /* if the current read buffer is filled, or the
230 last pushed-back char has been read and the saved buffer is
231 filled, result is true. */
232 if (pt->read_pos < pt->read_end
233 || (pt->read_buf == pt->putback_buf
234 && pt->saved_read_pos < pt->saved_read_end))
0f2d19dd 235 return SCM_BOOL_T;
ee149d03
JB
236 else
237 {
f12733c9 238 scm_ptob_descriptor *ptob = &scm_ptobs[SCM_PTOBNUM (port)];
ee149d03 239
affc96b5 240 if (ptob->input_waiting)
1bbd0b84 241 return SCM_BOOL(ptob->input_waiting (port));
ee149d03 242 else
6c951427 243 return SCM_BOOL_T;
ee149d03 244 }
0f2d19dd 245}
1bbd0b84 246#undef FUNC_NAME
0f2d19dd 247
6c951427 248/* Clear a port's read buffers, returning the contents. */
1bbd0b84
GB
249GUILE_PROC (scm_drain_input, "drain-input", 1, 0, 0,
250 (SCM port),
4079f87e
GB
251"Drains @var{PORT}'s read buffers (including any pushed-back characters)
252and returns the contents as a single string.")
1bbd0b84 253#define FUNC_NAME s_scm_drain_input
ee149d03 254{
840ae05d
JB
255 SCM result;
256 scm_port *pt = SCM_PTAB_ENTRY (port);
6c951427 257 int count;
840ae05d 258 char *dst;
ee149d03 259
1bbd0b84 260 SCM_VALIDATE_OPINPORT(1,port);
840ae05d 261
6c951427
GH
262 count = pt->read_end - pt->read_pos;
263 if (pt->read_buf == pt->putback_buf)
264 count += pt->saved_read_end - pt->saved_read_pos;
840ae05d 265
6c951427
GH
266 result = scm_makstr (count, 0);
267 dst = SCM_CHARS (result);
840ae05d
JB
268
269 while (pt->read_pos < pt->read_end)
6c951427
GH
270 *dst++ = *(pt->read_pos++);
271
272 if (pt->read_buf == pt->putback_buf)
840ae05d 273 {
6c951427
GH
274 while (pt->saved_read_pos < pt->saved_read_end)
275 *dst++ = *(pt->saved_read_pos++);
840ae05d 276 }
6c951427 277
840ae05d 278 return result;
ee149d03 279}
1bbd0b84 280#undef FUNC_NAME
0f2d19dd
JB
281
282\f
d68fee48 283/* Standard ports --- current input, output, error, and more(!). */
0f2d19dd 284
1bbd0b84
GB
285GUILE_PROC(scm_current_input_port, "current-input-port", 0, 0, 0,
286 (),
287"")
288#define FUNC_NAME s_scm_current_input_port
0f2d19dd
JB
289{
290 return scm_cur_inp;
291}
1bbd0b84 292#undef FUNC_NAME
0f2d19dd 293
1bbd0b84
GB
294GUILE_PROC(scm_current_output_port, "current-output-port", 0, 0, 0,
295 (),
296"")
297#define FUNC_NAME s_scm_current_output_port
0f2d19dd
JB
298{
299 return scm_cur_outp;
300}
1bbd0b84 301#undef FUNC_NAME
0f2d19dd 302
1bbd0b84
GB
303GUILE_PROC(scm_current_error_port, "current-error-port", 0, 0, 0,
304 (),
4079f87e
GB
305"Return the port to which errors and warnings should be sent (the
306@dfn{standard error} in Unix and C terminology).")
1bbd0b84 307#define FUNC_NAME s_scm_current_error_port
0f2d19dd
JB
308{
309 return scm_cur_errp;
310}
1bbd0b84 311#undef FUNC_NAME
0f2d19dd 312
1bbd0b84
GB
313GUILE_PROC(scm_current_load_port, "current-load-port", 0, 0, 0,
314 (),
315"")
316#define FUNC_NAME s_scm_current_load_port
31614d8e
MD
317{
318 return scm_cur_loadp;
319}
1bbd0b84 320#undef FUNC_NAME
31614d8e 321
1bbd0b84
GB
322GUILE_PROC(scm_set_current_input_port, "set-current-input-port", 1, 0, 0,
323 (SCM port),
4079f87e
GB
324"@deffnx primitive set-current-output-port port
325@deffnx primitive set-current-error-port port
326Change the ports returned by @code{current-input-port},
327@code{current-output-port} and @code{current-error-port}, respectively,
328so that they use the supplied @var{port} for input or output.")
1bbd0b84 329#define FUNC_NAME s_scm_set_current_input_port
0f2d19dd
JB
330{
331 SCM oinp = scm_cur_inp;
1bbd0b84 332 SCM_VALIDATE_OPINPORT(1,port);
0f2d19dd
JB
333 scm_cur_inp = port;
334 return oinp;
335}
1bbd0b84 336#undef FUNC_NAME
0f2d19dd
JB
337
338
1bbd0b84
GB
339GUILE_PROC(scm_set_current_output_port, "set-current-output-port", 1, 0, 0,
340 (SCM port),
341"")
342#define FUNC_NAME s_scm_set_current_output_port
0f2d19dd
JB
343{
344 SCM ooutp = scm_cur_outp;
78446828 345 port = SCM_COERCE_OUTPORT (port);
1bbd0b84 346 SCM_VALIDATE_OPOUTPORT(1,port);
0f2d19dd
JB
347 scm_cur_outp = port;
348 return ooutp;
349}
1bbd0b84 350#undef FUNC_NAME
0f2d19dd
JB
351
352
1bbd0b84
GB
353GUILE_PROC(scm_set_current_error_port, "set-current-error-port", 1, 0, 0,
354 (SCM port),
355"")
356#define FUNC_NAME s_scm_set_current_error_port
0f2d19dd
JB
357{
358 SCM oerrp = scm_cur_errp;
78446828 359 port = SCM_COERCE_OUTPORT (port);
1bbd0b84 360 SCM_VALIDATE_OPOUTPORT(1,port);
0f2d19dd
JB
361 scm_cur_errp = port;
362 return oerrp;
363}
1bbd0b84 364#undef FUNC_NAME
0f2d19dd
JB
365
366\f
840ae05d 367/* The port table --- an array of pointers to ports. */
0f2d19dd 368
840ae05d 369scm_port **scm_port_table;
0f2d19dd
JB
370
371int scm_port_table_size = 0; /* Number of ports in scm_port_table. */
372int scm_port_table_room = 20; /* Size of the array. */
373
ee149d03 374/* Add a port to the table. */
1cc91f1b 375
840ae05d 376scm_port *
a284e297 377scm_add_to_port_table (SCM port)
0f2d19dd 378{
840ae05d
JB
379 scm_port *entry;
380
0f2d19dd
JB
381 if (scm_port_table_size == scm_port_table_room)
382 {
ee149d03 383 void *newt = realloc ((char *) scm_port_table,
840ae05d 384 (scm_sizet) (sizeof (scm_port *)
ee149d03
JB
385 * scm_port_table_room * 2));
386 if (newt == NULL)
840ae05d
JB
387 scm_memory_error ("scm_add_to_port_table");
388 scm_port_table = (scm_port **) newt;
0f2d19dd
JB
389 scm_port_table_room *= 2;
390 }
840ae05d
JB
391 entry = (scm_port *) malloc (sizeof (scm_port));
392 if (entry == NULL)
393 scm_memory_error ("scm_add_to_port_table");
394
395 entry->port = port;
396 entry->entry = scm_port_table_size;
397 entry->revealed = 0;
398 entry->stream = 0;
399 entry->file_name = SCM_BOOL_F;
400 entry->line_number = 0;
401 entry->column_number = 0;
6c951427
GH
402 entry->putback_buf = 0;
403 entry->putback_buf_size = 0;
61e452ba 404 entry->rw_active = SCM_PORT_NEITHER;
0de97b83 405 entry->rw_random = 0;
840ae05d
JB
406
407 scm_port_table[scm_port_table_size] = entry;
408 scm_port_table_size++;
409
410 return entry;
0f2d19dd
JB
411}
412
6c951427 413/* Remove a port from the table and destroy it. */
1cc91f1b 414
0f2d19dd 415void
a284e297 416scm_remove_from_port_table (SCM port)
0f2d19dd 417{
840ae05d 418 scm_port *p = SCM_PTAB_ENTRY (port);
ee1e7e13 419 int i = p->entry;
6c951427 420
ee1e7e13
MD
421 if (i >= scm_port_table_size)
422 scm_wta (port, "Port not in table", "scm_remove_from_port_table");
6c951427
GH
423 if (p->putback_buf)
424 free (p->putback_buf);
840ae05d 425 free (p);
ee1e7e13
MD
426 /* Since we have just freed slot i we can shrink the table by moving
427 the last entry to that slot... */
428 if (i < scm_port_table_size - 1)
0f2d19dd 429 {
ee1e7e13
MD
430 scm_port_table[i] = scm_port_table[scm_port_table_size - 1];
431 scm_port_table[i]->entry = i;
0f2d19dd 432 }
0f2d19dd
JB
433 SCM_SETPTAB_ENTRY (port, 0);
434 scm_port_table_size--;
435}
436
fea6b4ea 437#ifdef GUILE_DEBUG
0f2d19dd
JB
438/* Undocumented functions for debugging. */
439/* Return the number of ports in the table. */
1cc91f1b 440
1bbd0b84
GB
441GUILE_PROC(scm_pt_size, "pt-size", 0, 0, 0,
442 (),
443"")
444#define FUNC_NAME s_scm_pt_size
0f2d19dd
JB
445{
446 return SCM_MAKINUM (scm_port_table_size);
447}
1bbd0b84 448#undef FUNC_NAME
0f2d19dd
JB
449
450/* Return the ith member of the port table. */
1bbd0b84
GB
451GUILE_PROC(scm_pt_member, "pt-member", 1, 0, 0,
452 (SCM member),
453"")
454#define FUNC_NAME s_scm_pt_member
0f2d19dd
JB
455{
456 int i;
47c6b75e 457 SCM_VALIDATE_INUM_COPY (1,member,i);
0f2d19dd
JB
458 if (i < 0 || i >= scm_port_table_size)
459 return SCM_BOOL_F;
460 else
461 return scm_port_table[i]->port;
462}
1bbd0b84 463#undef FUNC_NAME
0f2d19dd
JB
464#endif
465
466
d68fee48
JB
467\f
468/* Revealed counts --- an oddity inherited from SCSH. */
469
8b13c6b3
GH
470/* Find a port in the table and return its revealed count.
471 Also used by the garbage collector.
0f2d19dd 472 */
1cc91f1b 473
0f2d19dd 474int
a284e297 475scm_revealed_count (SCM port)
0f2d19dd
JB
476{
477 return SCM_REVEALED(port);
478}
479
480
481
482/* Return the revealed count for a port. */
483
1bbd0b84
GB
484GUILE_PROC(scm_port_revealed, "port-revealed", 1, 0, 0,
485 (SCM port),
4079f87e 486"Returns the revealed count for @var{port}.")
1bbd0b84 487#define FUNC_NAME s_scm_port_revealed
0f2d19dd 488{
78446828 489 port = SCM_COERCE_OUTPORT (port);
1bbd0b84 490 SCM_VALIDATE_PORT(1,port);
8b13c6b3 491 return SCM_MAKINUM (scm_revealed_count (port));
0f2d19dd 492}
1bbd0b84 493#undef FUNC_NAME
0f2d19dd
JB
494
495/* Set the revealed count for a port. */
1bbd0b84
GB
496GUILE_PROC(scm_set_port_revealed_x, "set-port-revealed!", 2, 0, 0,
497 (SCM port, SCM rcount),
4079f87e
GB
498"Sets the revealed count for a port to a given value.
499The return value is unspecified.")
1bbd0b84 500#define FUNC_NAME s_scm_set_port_revealed_x
0f2d19dd 501{
78446828 502 port = SCM_COERCE_OUTPORT (port);
1bbd0b84 503 SCM_VALIDATE_PORT(1,port);
47c6b75e 504 SCM_VALIDATE_INUM(2,rcount);
0f2d19dd 505 SCM_REVEALED (port) = SCM_INUM (rcount);
8b13c6b3 506 return SCM_UNSPECIFIED;
0f2d19dd 507}
1bbd0b84 508#undef FUNC_NAME
0f2d19dd 509
d68fee48
JB
510
511\f
512/* Retrieving a port's mode. */
513
eadd48de
GH
514/* Return the flags that characterize a port based on the mode
515 * string used to open a file for that port.
516 *
517 * See PORT FLAGS in scm.h
518 */
519
520long
a284e297 521scm_mode_bits (char *modes)
eadd48de
GH
522{
523 return (SCM_OPN
524 | (strchr (modes, 'r') || strchr (modes, '+') ? SCM_RDNG : 0)
525 | ( strchr (modes, 'w')
526 || strchr (modes, 'a')
527 || strchr (modes, '+') ? SCM_WRTNG : 0)
ee149d03
JB
528 | (strchr (modes, '0') ? SCM_BUF0 : 0)
529 | (strchr (modes, 'l') ? SCM_BUFLINE : 0));
eadd48de
GH
530}
531
532
533/* Return the mode flags from an open port.
534 * Some modes such as "append" are only used when opening
535 * a file and are not returned here. */
536
1bbd0b84
GB
537GUILE_PROC(scm_port_mode, "port-mode", 1, 0, 0,
538 (SCM port),
4079f87e
GB
539"Returns the port modes associated with the open port @var{port}. These
540will not necessarily be identical to the modes used when the port was
541opened, since modes such as \"append\" which are used only during
542port creation are not retained.")
1bbd0b84 543#define FUNC_NAME s_scm_port_mode
eadd48de
GH
544{
545 char modes[3];
546 modes[0] = '\0';
78446828
MV
547
548 port = SCM_COERCE_OUTPORT (port);
1bbd0b84 549 SCM_VALIDATE_OPPORT(1,port);
eadd48de
GH
550 if (SCM_CAR (port) & SCM_RDNG) {
551 if (SCM_CAR (port) & SCM_WRTNG)
552 strcpy (modes, "r+");
553 else
554 strcpy (modes, "r");
555 }
556 else if (SCM_CAR (port) & SCM_WRTNG)
557 strcpy (modes, "w");
558 if (SCM_CAR (port) & SCM_BUF0)
559 strcat (modes, "0");
560 return scm_makfromstr (modes, strlen (modes), 0);
561}
1bbd0b84 562#undef FUNC_NAME
eadd48de
GH
563
564
d68fee48
JB
565\f
566/* Closing ports. */
567
0f2d19dd
JB
568/* scm_close_port
569 * Call the close operation on a port object.
eadd48de 570 * see also scm_close.
0f2d19dd 571 */
1bbd0b84
GB
572GUILE_PROC(scm_close_port, "close-port", 1, 0, 0,
573 (SCM port),
4079f87e
GB
574"Close the specified port object. Returns @code{#t} if it successfully
575closes a port or @code{#f} if it was already
576closed. An exception may be raised if an error occurs, for example
577when flushing buffered output.
578See also @ref{Ports and File Descriptors, close}, for a procedure
579which can close file descriptors.")
1bbd0b84 580#define FUNC_NAME s_scm_close_port
0f2d19dd
JB
581{
582 scm_sizet i;
eadd48de
GH
583 int rv;
584
78446828
MV
585 port = SCM_COERCE_OUTPORT (port);
586
1bbd0b84 587 SCM_VALIDATE_PORT(1,port);
0f2d19dd 588 if (SCM_CLOSEDP (port))
eadd48de 589 return SCM_BOOL_F;
0f2d19dd 590 i = SCM_PTOBNUM (port);
affc96b5
GH
591 if (scm_ptobs[i].close)
592 rv = (scm_ptobs[i].close) (port);
eadd48de
GH
593 else
594 rv = 0;
0f2d19dd 595 scm_remove_from_port_table (port);
898a256f 596 SCM_SETAND_CAR (port, ~SCM_OPN);
1bbd0b84 597 return SCM_NEGATE_BOOL(rv < 0);
0f2d19dd 598}
1bbd0b84 599#undef FUNC_NAME
0f2d19dd 600
1bbd0b84
GB
601GUILE_PROC(scm_close_all_ports_except, "close-all-ports-except", 0, 0, 1,
602 (SCM ports),
4079f87e
GB
603"Close all open file ports used by the interpreter
604except for those supplied as arguments. This procedure
605is intended to be used before an exec call to close file descriptors
606which are not needed in the new process.Close all open file ports used by the interpreter
607except for those supplied as arguments. This procedure
608is intended to be used before an exec call to close file descriptors
609which are not needed in the new process.")
1bbd0b84 610#define FUNC_NAME s_scm_close_all_ports_except
0f2d19dd
JB
611{
612 int i = 0;
30939477 613 SCM_VALIDATE_CONS(1,ports);
0f2d19dd
JB
614 while (i < scm_port_table_size)
615 {
616 SCM thisport = scm_port_table[i]->port;
617 int found = 0;
618 SCM ports_ptr = ports;
619
620 while (SCM_NNULLP (ports_ptr))
621 {
78446828 622 SCM port = SCM_COERCE_OUTPORT (SCM_CAR (ports_ptr));
0f2d19dd 623 if (i == 0)
cdc95767 624 SCM_VALIDATE_OPPORT(SCM_ARG1,port);
0f2d19dd
JB
625 if (port == thisport)
626 found = 1;
627 ports_ptr = SCM_CDR (ports_ptr);
628 }
629 if (found)
630 i++;
631 else
632 /* i is not to be incremented here. */
633 scm_close_port (thisport);
634 }
0f2d19dd
JB
635 return SCM_UNSPECIFIED;
636}
1bbd0b84 637#undef FUNC_NAME
0f2d19dd 638
d68fee48
JB
639
640\f
641/* Utter miscellany. Gosh, we should clean this up some time. */
642
1bbd0b84
GB
643GUILE_PROC(scm_input_port_p, "input-port?", 1, 0, 0,
644 (SCM x),
645"")
646#define FUNC_NAME s_scm_input_port_p
0f2d19dd
JB
647{
648 if (SCM_IMP (x))
4a94d8ca 649 return SCM_BOOL_F;
1bbd0b84 650 return SCM_BOOL(SCM_INPORTP (x));
0f2d19dd 651}
1bbd0b84 652#undef FUNC_NAME
0f2d19dd 653
1bbd0b84
GB
654GUILE_PROC(scm_output_port_p, "output-port?", 1, 0, 0,
655 (SCM x),
656"")
657#define FUNC_NAME s_scm_output_port_p
0f2d19dd
JB
658{
659 if (SCM_IMP (x))
4a94d8ca
MD
660 return SCM_BOOL_F;
661 if (SCM_PORT_WITH_PS_P (x))
662 x = SCM_PORT_WITH_PS_PORT (x);
1bbd0b84 663 return SCM_BOOL(SCM_OUTPORTP (x));
0f2d19dd 664}
1bbd0b84 665#undef FUNC_NAME
0f2d19dd 666
1bbd0b84
GB
667GUILE_PROC(scm_port_closed_p, "port-closed?", 1, 0, 0,
668 (SCM port),
4079f87e 669"Returns @code{#t} if @var{port} is closed or @code{#f} if it is open.")
1bbd0b84 670#define FUNC_NAME s_scm_port_closed_p
60d0643d 671{
1bbd0b84
GB
672 SCM_VALIDATE_OPPORT(1,port);
673 return SCM_NEGATE_BOOL(SCM_OPPORTP (port));
60d0643d 674}
1bbd0b84 675#undef FUNC_NAME
0f2d19dd 676
1bbd0b84
GB
677GUILE_PROC(scm_eof_object_p, "eof-object?", 1, 0, 0,
678 (SCM x),
679"")
680#define FUNC_NAME s_scm_eof_object_p
0f2d19dd 681{
1bbd0b84 682 return SCM_BOOL(SCM_EOF_OBJECT_P (x));
0f2d19dd 683}
1bbd0b84 684#undef FUNC_NAME
0f2d19dd 685
1bbd0b84
GB
686GUILE_PROC(scm_force_output, "force-output", 0, 1, 0,
687 (SCM port),
4079f87e
GB
688"Flush the specified output port, or the current output port if @var{port}
689is omitted. The current output buffer contents are passed to the
690underlying port implementation (e.g., in the case of fports, the
691data will be written to the file and the output buffer will be cleared.)
692It has no effect on an unbuffered port.
693
694The return value is unspecified.")
1bbd0b84 695#define FUNC_NAME s_scm_force_output
0f2d19dd
JB
696{
697 if (SCM_UNBNDP (port))
3e877d15 698 port = scm_cur_outp;
0f2d19dd 699 else
78446828
MV
700 {
701 port = SCM_COERCE_OUTPORT (port);
1bbd0b84 702 SCM_VALIDATE_OPOUTPORT(1,port);
78446828 703 }
affc96b5 704 scm_flush (port);
ee149d03 705 return SCM_UNSPECIFIED;
0f2d19dd 706}
1bbd0b84 707#undef FUNC_NAME
0f2d19dd 708
1bbd0b84
GB
709GUILE_PROC (scm_flush_all_ports, "flush-all-ports", 0, 0, 0,
710 (),
4079f87e
GB
711"Equivalent to calling @code{force-output} on
712all open output ports. The return value is unspecified.")
1bbd0b84 713#define FUNC_NAME s_scm_flush_all_ports
89ea5b7c
GH
714{
715 int i;
716
717 for (i = 0; i < scm_port_table_size; i++)
718 {
ee149d03 719 if (SCM_OPOUTPORTP (scm_port_table[i]->port))
affc96b5 720 scm_flush (scm_port_table[i]->port);
89ea5b7c
GH
721 }
722 return SCM_UNSPECIFIED;
723}
1bbd0b84 724#undef FUNC_NAME
0f2d19dd 725
1bbd0b84
GB
726GUILE_PROC(scm_read_char, "read-char", 0, 1, 0,
727 (SCM port),
728"")
729#define FUNC_NAME s_scm_read_char
0f2d19dd
JB
730{
731 int c;
732 if (SCM_UNBNDP (port))
334341aa 733 port = scm_cur_inp;
1bbd0b84 734 SCM_VALIDATE_OPINPORT(1,port);
b7f3516f 735 c = scm_getc (port);
0f2d19dd
JB
736 if (EOF == c)
737 return SCM_EOF_VAL;
738 return SCM_MAKICHR (c);
739}
1bbd0b84 740#undef FUNC_NAME
0f2d19dd 741
5c070ca7 742/* this should only be called when the read buffer is empty. it
affc96b5 743 tries to refill the read buffer. it returns the first char from
5c070ca7 744 the port, which is either EOF or *(pt->read_pos). */
6c951427 745int
affc96b5 746scm_fill_input (SCM port)
6c951427 747{
283a1a0e
GH
748 scm_port *pt = SCM_PTAB_ENTRY (port);
749
6c951427
GH
750 if (pt->read_buf == pt->putback_buf)
751 {
752 /* finished reading put-back chars. */
753 pt->read_buf = pt->saved_read_buf;
754 pt->read_pos = pt->saved_read_pos;
755 pt->read_end = pt->saved_read_end;
756 pt->read_buf_size = pt->saved_read_buf_size;
757 if (pt->read_pos < pt->read_end)
5c070ca7 758 return *(pt->read_pos);
6c951427 759 }
affc96b5 760 return scm_ptobs[SCM_PTOBNUM (port)].fill_input (port);
6c951427
GH
761}
762
ee149d03 763int
a284e297 764scm_getc (SCM port)
0f2d19dd
JB
765{
766 int c;
840ae05d 767 scm_port *pt = SCM_PTAB_ENTRY (port);
ee149d03 768
840ae05d
JB
769 if (pt->rw_active == SCM_PORT_WRITE)
770 {
affc96b5
GH
771 /* may be marginally faster than calling scm_flush. */
772 scm_ptobs[SCM_PTOBNUM (port)].flush (port);
840ae05d 773 }
6c951427 774
5c070ca7
GH
775 if (pt->rw_random)
776 pt->rw_active = SCM_PORT_READ;
777
778 if (pt->read_pos >= pt->read_end)
ee149d03 779 {
affc96b5 780 if (scm_fill_input (port) == EOF)
5c070ca7 781 return EOF;
ee149d03
JB
782 }
783
5c070ca7 784 c = *(pt->read_pos++);
840ae05d 785
ee149d03
JB
786 if (c == '\n')
787 {
788 SCM_INCLINE (port);
789 }
790 else if (c == '\t')
791 {
792 SCM_TABCOL (port);
793 }
794 else
795 {
796 SCM_INCCOL (port);
797 }
798
799 return c;
0f2d19dd
JB
800}
801
ee149d03 802void
a284e297 803scm_putc (char c, SCM port)
ee149d03 804{
265e6a4d 805 scm_lfwrite (&c, 1, port);
ee149d03 806}
3cb988bd 807
ee149d03 808void
a284e297 809scm_puts (char *s, SCM port)
3cb988bd 810{
265e6a4d 811 scm_lfwrite (s, strlen (s), port);
ee149d03 812}
3cb988bd 813
ee149d03 814void
a284e297 815scm_lfwrite (char *ptr, scm_sizet size, SCM port)
ee149d03 816{
840ae05d 817 scm_port *pt = SCM_PTAB_ENTRY (port);
f12733c9 818 scm_ptob_descriptor *ptob = &scm_ptobs[SCM_PTOBNUM (port)];
3e2043c4 819
840ae05d 820 if (pt->rw_active == SCM_PORT_READ)
affc96b5 821 scm_end_input (port);
283a1a0e 822
31703ab8 823 ptob->write (port, ptr, size);
840ae05d
JB
824
825 if (pt->rw_random)
826 pt->rw_active = SCM_PORT_WRITE;
ee149d03 827}
3cb988bd 828
3cb988bd 829
ee149d03 830void
a284e297 831scm_flush (SCM port)
ee149d03
JB
832{
833 scm_sizet i = SCM_PTOBNUM (port);
affc96b5 834 (scm_ptobs[i].flush) (port);
ee149d03
JB
835}
836
283a1a0e 837void
a284e297 838scm_end_input (SCM port)
283a1a0e
GH
839{
840 int offset;
841 scm_port *pt = SCM_PTAB_ENTRY (port);
842
843 if (pt->read_buf == pt->putback_buf)
844 {
845 offset = pt->read_end - pt->read_pos;
846 pt->read_buf = pt->saved_read_buf;
847 pt->read_pos = pt->saved_read_pos;
848 pt->read_end = pt->saved_read_end;
849 pt->read_buf_size = pt->saved_read_buf_size;
850 }
851 else
852 offset = 0;
853
affc96b5 854 scm_ptobs[SCM_PTOBNUM (port)].end_input (port, offset);
283a1a0e
GH
855}
856
ee149d03
JB
857\f
858
859
860void
a284e297 861scm_ungetc (int c, SCM port)
ee149d03 862{
840ae05d
JB
863 scm_port *pt = SCM_PTAB_ENTRY (port);
864
6c951427
GH
865 if (pt->read_buf == pt->putback_buf)
866 /* already using the put-back buffer. */
867 {
868 /* enlarge putback_buf if necessary. */
869 if (pt->read_end == pt->read_buf + pt->read_buf_size
870 && pt->read_buf == pt->read_pos)
871 {
872 int new_size = pt->read_buf_size * 2;
873 unsigned char *tmp =
874 (unsigned char *) realloc (pt->putback_buf, new_size);
875
876 if (tmp == NULL)
877 scm_memory_error ("scm_ungetc");
878 pt->read_pos = pt->read_buf = pt->putback_buf = tmp;
879 pt->read_end = pt->read_buf + pt->read_buf_size;
880 pt->read_buf_size = pt->putback_buf_size = new_size;
881 }
882
883 /* shift any existing bytes to buffer + 1. */
884 if (pt->read_pos == pt->read_end)
885 pt->read_end = pt->read_buf + 1;
886 else if (pt->read_pos != pt->read_buf + 1)
887 {
888 int count = pt->read_end - pt->read_pos;
889
890 memmove (pt->read_buf + 1, pt->read_pos, count);
891 pt->read_end = pt->read_buf + 1 + count;
892 }
893
894 pt->read_pos = pt->read_buf;
895 }
896 else
897 /* switch to the put-back buffer. */
898 {
899 if (pt->putback_buf == NULL)
900 {
6e2e75db 901 pt->putback_buf = (char *) malloc (SCM_INITIAL_PUTBACK_BUF_SIZE);
6c951427
GH
902 if (pt->putback_buf == NULL)
903 scm_memory_error ("scm_ungetc");
904 pt->putback_buf_size = SCM_INITIAL_PUTBACK_BUF_SIZE;
905 }
906
907 pt->saved_read_buf = pt->read_buf;
908 pt->saved_read_pos = pt->read_pos;
909 pt->saved_read_end = pt->read_end;
910 pt->saved_read_buf_size = pt->read_buf_size;
911
912 pt->read_pos = pt->read_buf = pt->putback_buf;
913 pt->read_end = pt->read_buf + 1;
914 pt->read_buf_size = pt->putback_buf_size;
915 }
916
917 *pt->read_buf = c;
ee149d03 918
840ae05d
JB
919 if (pt->rw_random)
920 pt->rw_active = SCM_PORT_READ;
921
ee149d03
JB
922 if (c == '\n')
923 {
924 /* What should col be in this case?
925 * We'll leave it at -1.
926 */
927 SCM_LINUM (port) -= 1;
928 }
929 else
930 SCM_COL(port) -= 1;
931}
932
933
934void
a284e297 935scm_ungets (char *s, int n, SCM port)
ee149d03
JB
936{
937 /* This is simple minded and inefficient, but unreading strings is
938 * probably not a common operation, and remember that line and
939 * column numbers have to be handled...
940 *
941 * Please feel free to write an optimized version!
942 */
943 while (n--)
944 scm_ungetc (s[n], port);
945}
946
947
1bbd0b84
GB
948GUILE_PROC(scm_peek_char, "peek-char", 0, 1, 0,
949 (SCM port),
950"")
951#define FUNC_NAME s_scm_peek_char
ee149d03
JB
952{
953 int c;
954 if (SCM_UNBNDP (port))
955 port = scm_cur_inp;
956 else
1bbd0b84 957 SCM_VALIDATE_OPINPORT(1,port);
ee149d03
JB
958 c = scm_getc (port);
959 if (EOF == c)
960 return SCM_EOF_VAL;
961 scm_ungetc (c, port);
962 return SCM_MAKICHR (c);
3cb988bd 963}
1bbd0b84 964#undef FUNC_NAME
3cb988bd 965
1bbd0b84
GB
966GUILE_PROC (scm_unread_char, "unread-char", 2, 0, 0,
967 (SCM cobj, SCM port),
4079f87e
GB
968"Place @var{char} in @var{port} so that it will be read by the
969next read operation. If called multiple times, the unread characters
970will be read again in last-in first-out order. If @var{port} is
971not supplied, the current input port is used.")
1bbd0b84 972#define FUNC_NAME s_scm_unread_char
0f2d19dd
JB
973{
974 int c;
975
1bbd0b84 976 SCM_VALIDATE_CHAR(1,cobj);
0f2d19dd
JB
977 if (SCM_UNBNDP (port))
978 port = scm_cur_inp;
979 else
cfaba30e 980 SCM_VALIDATE_OPINPORT(2,port);
0f2d19dd
JB
981
982 c = SCM_ICHR (cobj);
983
b7f3516f 984 scm_ungetc (c, port);
0f2d19dd
JB
985 return cobj;
986}
1bbd0b84 987#undef FUNC_NAME
0f2d19dd 988
1bbd0b84
GB
989GUILE_PROC (scm_unread_string, "unread-string", 2, 0, 0,
990 (SCM str, SCM port),
4079f87e
GB
991"Place the string @var{str} in @var{port} so that its characters will be
992read in subsequent read operations. If called multiple times, the
993unread characters will be read again in last-in first-out order. If
994@var{port} is not supplied, the current-input-port is used.")
1bbd0b84 995#define FUNC_NAME s_scm_unread_string
ee1e7e13 996{
1bbd0b84 997 SCM_VALIDATE_STRING(1,str);
ee1e7e13
MD
998 if (SCM_UNBNDP (port))
999 port = scm_cur_inp;
1000 else
cfaba30e 1001 SCM_VALIDATE_OPINPORT(2,port);
ee1e7e13 1002
d1c90db5 1003 scm_ungets (SCM_ROUCHARS (str), SCM_LENGTH (str), port);
ee1e7e13
MD
1004
1005 return str;
1006}
1bbd0b84 1007#undef FUNC_NAME
ee1e7e13 1008
1bbd0b84
GB
1009GUILE_PROC (scm_seek, "seek", 3, 0, 0,
1010 (SCM object, SCM offset, SCM whence),
4079f87e
GB
1011"Sets the current position of @var{fd/port} to the integer @var{offset},
1012which is interpreted according to the value of @var{whence}.
1013
1014One of the following variables should be supplied
1015for @var{whence}:
1016@defvar SEEK_SET
1017Seek from the beginning of the file.
1018@end defvar
1019@defvar SEEK_CUR
1020Seek from the current position.
1021@end defvar
1022@defvar SEEK_END
1023Seek from the end of the file.
1024@end defvar
1025
1026If @var{fd/port} is a file descriptor, the underlying system call is
1027@code{lseek}. @var{port} may be a string port.
1028
1029The value returned is the new position in the file. This means that
1030the current position of a port can be obtained using:
1031@smalllisp
1032(seek port 0 SEEK_CUR)
1033@end smalllisp")
1bbd0b84 1034#define FUNC_NAME s_scm_seek
840ae05d
JB
1035{
1036 off_t off;
1037 off_t rv;
1038 int how;
1039
1040 object = SCM_COERCE_OUTPORT (object);
1041
1bbd0b84 1042 off = SCM_NUM2LONG (2,offset);
47c6b75e 1043 SCM_VALIDATE_INUM_COPY(3,whence,how);
840ae05d 1044 if (how != SEEK_SET && how != SEEK_CUR && how != SEEK_END)
1bbd0b84 1045 SCM_OUT_OF_RANGE (3, whence);
0c95b57d 1046 if (SCM_OPPORTP (object))
840ae05d 1047 {
f12733c9 1048 scm_ptob_descriptor *ptob = scm_ptobs + SCM_PTOBNUM (object);
840ae05d
JB
1049
1050 if (!ptob->seek)
1bbd0b84
GB
1051 SCM_MISC_ERROR ("port is not seekable",
1052 scm_cons (object, SCM_EOL));
840ae05d 1053 else
7dcb364d 1054 rv = ptob->seek (object, off, how);
840ae05d
JB
1055 }
1056 else /* file descriptor?. */
1057 {
47c6b75e 1058 SCM_VALIDATE_INUM(1,object);
840ae05d
JB
1059 rv = lseek (SCM_INUM (object), off, how);
1060 if (rv == -1)
1bbd0b84 1061 SCM_SYSERROR;
840ae05d
JB
1062 }
1063 return scm_long2num (rv);
1064}
1bbd0b84 1065#undef FUNC_NAME
840ae05d 1066
1bbd0b84
GB
1067GUILE_PROC (scm_truncate_file, "truncate-file", 1, 1, 0,
1068 (SCM object, SCM length),
4079f87e
GB
1069"Truncates the object referred to by @var{obj} to at most @var{size} bytes.
1070@var{obj} can be a string containing a file name or an integer file
1071descriptor or a port. @var{size} may be omitted if @var{obj} is not
1072a file name, in which case the truncation occurs at the current port.
1073position.
1074
1075The return value is unspecified.")
1bbd0b84 1076#define FUNC_NAME s_scm_truncate_file
840ae05d 1077{
69bc9ff3
GH
1078 int rv;
1079 off_t c_length;
1080
1081 /* object can be a port, fdes or filename. */
840ae05d 1082
840ae05d
JB
1083 if (SCM_UNBNDP (length))
1084 {
69bc9ff3 1085 /* must supply length if object is a filename. */
0c95b57d 1086 if (SCM_ROSTRINGP (object))
1bbd0b84 1087 scm_wrong_num_args (SCM_FUNC_NAME);
69bc9ff3 1088
c94577b4 1089 length = scm_seek (object, SCM_INUM0, SCM_MAKINUM (SEEK_CUR));
840ae05d 1090 }
1bbd0b84 1091 c_length = SCM_NUM2LONG (2,length);
69bc9ff3 1092 if (c_length < 0)
1bbd0b84 1093 SCM_MISC_ERROR ("negative offset", SCM_EOL);
3fe6190f 1094
69bc9ff3
GH
1095 object = SCM_COERCE_OUTPORT (object);
1096 if (SCM_INUMP (object))
1097 {
1098 SCM_SYSCALL (rv = ftruncate (SCM_INUM (object), c_length));
1099 }
0c95b57d 1100 else if (SCM_OPOUTPORTP (object))
69bc9ff3
GH
1101 {
1102 scm_port *pt = SCM_PTAB_ENTRY (object);
f12733c9 1103 scm_ptob_descriptor *ptob = scm_ptobs + SCM_PTOBNUM (object);
69bc9ff3 1104
affc96b5 1105 if (!ptob->truncate)
1bbd0b84 1106 SCM_MISC_ERROR ("port is not truncatable", SCM_EOL);
69bc9ff3 1107 if (pt->rw_active == SCM_PORT_READ)
affc96b5 1108 scm_end_input (object);
69bc9ff3 1109 else if (pt->rw_active == SCM_PORT_WRITE)
affc96b5 1110 ptob->flush (object);
69bc9ff3 1111
affc96b5 1112 ptob->truncate (object, c_length);
69bc9ff3
GH
1113 rv = 0;
1114 }
1115 else
1116 {
1bbd0b84 1117 SCM_VALIDATE_ROSTRING(1,object);
69bc9ff3
GH
1118 SCM_COERCE_SUBSTR (object);
1119 SCM_SYSCALL (rv = truncate (SCM_ROCHARS (object), c_length));
1120 }
1121 if (rv == -1)
1bbd0b84 1122 SCM_SYSERROR;
840ae05d
JB
1123 return SCM_UNSPECIFIED;
1124}
1bbd0b84 1125#undef FUNC_NAME
840ae05d 1126
1bbd0b84
GB
1127GUILE_PROC (scm_port_line, "port-line", 1, 0, 0,
1128 (SCM port),
1129"")
1130#define FUNC_NAME s_scm_port_line
0f2d19dd 1131{
78446828 1132 port = SCM_COERCE_OUTPORT (port);
1bbd0b84 1133 SCM_VALIDATE_OPENPORT(1,port);
360fc44c 1134 return SCM_MAKINUM (SCM_LINUM (port));
0f2d19dd 1135}
1bbd0b84 1136#undef FUNC_NAME
0f2d19dd 1137
1bbd0b84
GB
1138GUILE_PROC (scm_set_port_line_x, "set-port-line!", 2, 0, 0,
1139 (SCM port, SCM line),
1140"")
1141#define FUNC_NAME s_scm_set_port_line_x
d043d8c2 1142{
360fc44c 1143 port = SCM_COERCE_OUTPORT (port);
1bbd0b84 1144 SCM_VALIDATE_OPENPORT(1,port);
47c6b75e 1145 SCM_VALIDATE_INUM(2,line);
d043d8c2
MD
1146 return SCM_PTAB_ENTRY (port)->line_number = SCM_INUM (line);
1147}
1bbd0b84 1148#undef FUNC_NAME
d043d8c2 1149
1bbd0b84
GB
1150GUILE_PROC (scm_port_column, "port-column", 1, 0, 0,
1151 (SCM port),
4079f87e
GB
1152"@deffnx primitive port-line [input-port]
1153Return the current column number or line number of @var{input-port},
1154using the current input port if none is specified. If the number is
1155unknown, the result is #f. Otherwise, the result is a 0-origin integer
1156- i.e. the first character of the first line is line 0, column 0.
1157(However, when you display a file position, for example in an error
1158message, we recommand you add 1 to get 1-origin integers. This is
1159because lines and column numbers traditionally start with 1, and that is
1160what non-programmers will find most natural.)")
1bbd0b84 1161#define FUNC_NAME s_scm_port_column
0f2d19dd 1162{
78446828 1163 port = SCM_COERCE_OUTPORT (port);
1bbd0b84 1164 SCM_VALIDATE_OPENPORT(1,port);
360fc44c 1165 return SCM_MAKINUM (SCM_COL (port));
0f2d19dd 1166}
1bbd0b84 1167#undef FUNC_NAME
0f2d19dd 1168
1bbd0b84
GB
1169GUILE_PROC (scm_set_port_column_x, "set-port-column!", 2, 0, 0,
1170 (SCM port, SCM column),
4079f87e
GB
1171"@deffnx primitive set-port-line! [input-port] line
1172Set the current column or line number of @var{input-port}, using the
1173current input port if none is specified.")
1bbd0b84 1174#define FUNC_NAME s_scm_set_port_column_x
d043d8c2 1175{
360fc44c 1176 port = SCM_COERCE_OUTPORT (port);
1bbd0b84 1177 SCM_VALIDATE_OPENPORT(1,port);
47c6b75e 1178 SCM_VALIDATE_INUM(2,column);
d043d8c2
MD
1179 return SCM_PTAB_ENTRY (port)->column_number = SCM_INUM (column);
1180}
1bbd0b84 1181#undef FUNC_NAME
d043d8c2 1182
1bbd0b84
GB
1183GUILE_PROC (scm_port_filename, "port-filename", 1, 0, 0,
1184 (SCM port),
4079f87e
GB
1185"Return the filename associated with @var{port}. This function returns
1186the strings "standard input", "standard output" and "standard error"
1187when called on the current input, output and error ports respectively.")
1bbd0b84 1188#define FUNC_NAME s_scm_port_filename
0f2d19dd 1189{
78446828 1190 port = SCM_COERCE_OUTPORT (port);
1bbd0b84 1191 SCM_VALIDATE_OPENPORT(1,port);
360fc44c 1192 return SCM_PTAB_ENTRY (port)->file_name;
0f2d19dd 1193}
1bbd0b84 1194#undef FUNC_NAME
0f2d19dd 1195
1bbd0b84
GB
1196GUILE_PROC (scm_set_port_filename_x, "set-port-filename!", 2, 0, 0,
1197 (SCM port, SCM filename),
4079f87e
GB
1198"Change the filename associated with @var{port}, using the current input
1199port if none is specified. Note that this does not change the port's
1200source of data, but only the value that is returned by
1201@code{port-filename} and reported in diagnostic output.")
1bbd0b84 1202#define FUNC_NAME s_scm_set_port_filename_x
d14af9f2 1203{
360fc44c 1204 port = SCM_COERCE_OUTPORT (port);
1bbd0b84 1205 SCM_VALIDATE_OPENPORT(1,port);
360fc44c 1206 /* We allow the user to set the filename to whatever he likes. */
d14af9f2
MD
1207 return SCM_PTAB_ENTRY (port)->file_name = filename;
1208}
1bbd0b84 1209#undef FUNC_NAME
d14af9f2 1210
0f2d19dd
JB
1211#ifndef ttyname
1212extern char * ttyname();
1213#endif
1214
f12733c9
MD
1215void
1216scm_print_port_mode (SCM exp, SCM port)
1217{
1218 scm_puts (SCM_CLOSEDP (exp)
1219 ? "closed: "
1220 : (SCM_RDNG & SCM_CAR (exp)
1221 ? (SCM_WRTNG & SCM_CAR (exp)
1222 ? "input-output: "
1223 : "input: ")
1224 : (SCM_WRTNG & SCM_CAR (exp)
1225 ? "output: "
1226 : "bogus: ")),
1227 port);
1228}
1cc91f1b 1229
f12733c9
MD
1230int
1231scm_port_print (SCM exp, SCM port, scm_print_state *pstate)
0f2d19dd 1232{
f12733c9
MD
1233 char *type = SCM_PTOBNAME (SCM_PTOBNUM (exp));
1234 if (!type)
1235 type = "port";
b7f3516f 1236 scm_puts ("#<", port);
f12733c9 1237 scm_print_port_mode (exp, port);
b7f3516f
TT
1238 scm_puts (type, port);
1239 scm_putc (' ', port);
f12733c9 1240 scm_intprint (SCM_CDR (exp), 16, port);
b7f3516f 1241 scm_putc ('>', port);
f12733c9 1242 return 1;
0f2d19dd
JB
1243}
1244
f12733c9
MD
1245extern void scm_make_fptob ();
1246extern void scm_make_stptob ();
1247extern void scm_make_sfptob ();
1cc91f1b 1248
0f2d19dd
JB
1249void
1250scm_ports_prehistory ()
0f2d19dd
JB
1251{
1252 scm_numptob = 0;
f12733c9 1253 scm_ptobs = (scm_ptob_descriptor *) malloc (sizeof (scm_ptob_descriptor));
0f2d19dd
JB
1254
1255 /* WARNING: These scm_newptob calls must be done in this order.
1256 * They must agree with the port declarations in tags.h.
1257 */
f12733c9
MD
1258 /* scm_tc16_fport = */ scm_make_fptob ();
1259 /* scm_tc16_pipe was here */ scm_make_fptob (); /* dummy. */
1260 /* scm_tc16_strport = */ scm_make_stptob ();
1261 /* scm_tc16_sfport = */ scm_make_sfptob ();
0f2d19dd 1262}
0f2d19dd
JB
1263
1264\f
ee149d03 1265
d68fee48 1266/* Void ports. */
0f2d19dd 1267
f12733c9 1268long scm_tc16_void_port = 0;
0f2d19dd 1269
ee149d03 1270static void
0f88a8f3 1271flush_void_port (SCM port)
0f2d19dd 1272{
3cb988bd 1273}
1cc91f1b 1274
283a1a0e 1275static void
affc96b5 1276end_input_void_port (SCM port, int offset)
283a1a0e
GH
1277{
1278}
1279
31703ab8
GH
1280static void
1281write_void_port (SCM port, void *data, size_t size)
1282{
1283}
1284
0f2d19dd 1285SCM
a284e297 1286scm_void_port (char *mode_str)
0f2d19dd
JB
1287{
1288 int mode_bits;
1289 SCM answer;
840ae05d 1290 scm_port * pt;
0f2d19dd
JB
1291
1292 SCM_NEWCELL (answer);
1293 SCM_DEFER_INTS;
1294 mode_bits = scm_mode_bits (mode_str);
1295 pt = scm_add_to_port_table (answer);
0f2d19dd 1296 SCM_SETPTAB_ENTRY (answer, pt);
ee149d03
JB
1297 SCM_SETSTREAM (answer, 0);
1298 SCM_SETCAR (answer, scm_tc16_void_port | mode_bits);
0f2d19dd
JB
1299 SCM_ALLOW_INTS;
1300 return answer;
1301}
1302
1303
1bbd0b84
GB
1304GUILE_PROC (scm_sys_make_void_port, "%make-void-port", 1, 0, 0,
1305 (SCM mode),
4079f87e
GB
1306"Create and return a new void port. The @var{mode} argument describes
1307the input/output modes for this port; for a description, see the
1308documentation for @code{open-file} in @ref{File Ports}.")
1bbd0b84 1309#define FUNC_NAME s_scm_sys_make_void_port
0f2d19dd 1310{
1bbd0b84 1311 SCM_VALIDATE_ROSTRING(1,mode);
89958ad0 1312 SCM_COERCE_SUBSTR (mode);
0f2d19dd
JB
1313 return scm_void_port (SCM_ROCHARS (mode));
1314}
1bbd0b84 1315#undef FUNC_NAME
0f2d19dd 1316
0f2d19dd 1317\f
89545eba 1318/* Initialization. */
1cc91f1b 1319
0f2d19dd
JB
1320void
1321scm_init_ports ()
0f2d19dd 1322{
840ae05d
JB
1323 /* lseek() symbols. */
1324 scm_sysintern ("SEEK_SET", SCM_MAKINUM (SEEK_SET));
1325 scm_sysintern ("SEEK_CUR", SCM_MAKINUM (SEEK_CUR));
1326 scm_sysintern ("SEEK_END", SCM_MAKINUM (SEEK_END));
1327
affc96b5 1328 scm_tc16_void_port = scm_make_port_type ("void", 0, write_void_port);
0f2d19dd
JB
1329#include "ports.x"
1330}