* net_db.c (scm_resolv_error): Cast result from hstrerror.
[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);
8aa011a1 103static void write_void_port (SCM port, const void *data, size_t size);
0f2d19dd 104
0f2d19dd 105long
f12733c9 106scm_make_port_type (char *name,
affc96b5 107 int (*fill_input) (SCM port),
8aa011a1 108 void (*write) (SCM port, const 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
3b3b36dd 215SCM_DEFINE (scm_char_ready_p, "char-ready?", 0, 1, 0,
1bbd0b84 216 (SCM port),
b380b885 217 "")
1bbd0b84 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
3b3b36dd 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. */
a1ec6916 249SCM_DEFINE (scm_drain_input, "drain-input", 1, 0, 0,
1bbd0b84 250 (SCM port),
b380b885
MD
251 "Drains @var{PORT}'s read buffers (including any pushed-back characters)\n"
252 "and 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
3b3b36dd 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
3b3b36dd 285SCM_DEFINE (scm_current_input_port, "current-input-port", 0, 0, 0,
1bbd0b84 286 (),
b380b885 287 "")
1bbd0b84 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
3b3b36dd 294SCM_DEFINE (scm_current_output_port, "current-output-port", 0, 0, 0,
1bbd0b84 295 (),
b380b885 296 "")
1bbd0b84 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
3b3b36dd 303SCM_DEFINE (scm_current_error_port, "current-error-port", 0, 0, 0,
1bbd0b84 304 (),
b380b885
MD
305 "Return the port to which errors and warnings should be sent (the\n"
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
3b3b36dd 313SCM_DEFINE (scm_current_load_port, "current-load-port", 0, 0, 0,
1bbd0b84 314 (),
b380b885 315 "")
1bbd0b84 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
3b3b36dd 322SCM_DEFINE (scm_set_current_input_port, "set-current-input-port", 1, 0, 0,
1bbd0b84 323 (SCM port),
b380b885
MD
324 "@deffnx primitive set-current-output-port port\n"
325 "@deffnx primitive set-current-error-port port\n"
326 "Change the ports returned by @code{current-input-port},\n"
327 "@code{current-output-port} and @code{current-error-port}, respectively,\n"
328 "so 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;
3b3b36dd 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
3b3b36dd 339SCM_DEFINE (scm_set_current_output_port, "set-current-output-port", 1, 0, 0,
1bbd0b84 340 (SCM port),
b380b885 341 "")
1bbd0b84 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);
3b3b36dd 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
3b3b36dd 353SCM_DEFINE (scm_set_current_error_port, "set-current-error-port", 1, 0, 0,
1bbd0b84 354 (SCM port),
b380b885 355 "")
1bbd0b84 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);
3b3b36dd 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
3b3b36dd 441SCM_DEFINE (scm_pt_size, "pt-size", 0, 0, 0,
1bbd0b84 442 (),
b380b885 443 "")
1bbd0b84 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. */
3b3b36dd 451SCM_DEFINE (scm_pt_member, "pt-member", 1, 0, 0,
1bbd0b84 452 (SCM member),
b380b885 453 "")
1bbd0b84 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
3b3b36dd 484SCM_DEFINE (scm_port_revealed, "port-revealed", 1, 0, 0,
1bbd0b84 485 (SCM port),
b380b885 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);
3b3b36dd 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. */
3b3b36dd 496SCM_DEFINE (scm_set_port_revealed_x, "set-port-revealed!", 2, 0, 0,
1bbd0b84 497 (SCM port, SCM rcount),
b380b885
MD
498 "Sets the revealed count for a port to a given value. \n"
499 "The return value is unspecified.")
1bbd0b84 500#define FUNC_NAME s_scm_set_port_revealed_x
0f2d19dd 501{
78446828 502 port = SCM_COERCE_OUTPORT (port);
3b3b36dd
GB
503 SCM_VALIDATE_PORT (1,port);
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
3b3b36dd 537SCM_DEFINE (scm_port_mode, "port-mode", 1, 0, 0,
1bbd0b84 538 (SCM port),
b380b885
MD
539 "Returns the port modes associated with the open port @var{port}. These\n"
540 "will not necessarily be identical to the modes used when the port was\n"
541 "opened, since modes such as \"append\" which are used only during\n"
542 "port 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);
3b3b36dd 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 */
3b3b36dd 572SCM_DEFINE (scm_close_port, "close-port", 1, 0, 0,
1bbd0b84 573 (SCM port),
b380b885
MD
574 "Close the specified port object. Returns @code{#t} if it successfully\n"
575 "closes a port or @code{#f} if it was already\n"
576 "closed. An exception may be raised if an error occurs, for example\n"
577 "when flushing buffered output.\n"
578 "See also @ref{Ports and File Descriptors, close}, for a procedure\n"
579 "which 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
3b3b36dd 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
3b3b36dd 601SCM_DEFINE (scm_close_all_ports_except, "close-all-ports-except", 0, 0, 1,
1bbd0b84 602 (SCM ports),
b380b885
MD
603 "Close all open file ports used by the interpreter\n"
604 "except for those supplied as arguments. This procedure\n"
605 "is intended to be used before an exec call to close file descriptors\n"
606 "which are not needed in the new process.Close all open file ports used by the interpreter\n"
607 "except for those supplied as arguments. This procedure\n"
608 "is intended to be used before an exec call to close file descriptors\n"
609 "which 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;
3b3b36dd 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)
3b3b36dd 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
3b3b36dd 643SCM_DEFINE (scm_input_port_p, "input-port?", 1, 0, 0,
1bbd0b84 644 (SCM x),
b380b885 645 "")
1bbd0b84 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
3b3b36dd 654SCM_DEFINE (scm_output_port_p, "output-port?", 1, 0, 0,
1bbd0b84 655 (SCM x),
b380b885 656 "")
1bbd0b84 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
3b3b36dd 667SCM_DEFINE (scm_port_closed_p, "port-closed?", 1, 0, 0,
1bbd0b84 668 (SCM port),
b380b885 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{
c1bfcf60 672 SCM_VALIDATE_PORT (1,port);
1bbd0b84 673 return SCM_NEGATE_BOOL(SCM_OPPORTP (port));
60d0643d 674}
1bbd0b84 675#undef FUNC_NAME
0f2d19dd 676
3b3b36dd 677SCM_DEFINE (scm_eof_object_p, "eof-object?", 1, 0, 0,
1bbd0b84 678 (SCM x),
b380b885 679 "")
1bbd0b84 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
3b3b36dd 686SCM_DEFINE (scm_force_output, "force-output", 0, 1, 0,
1bbd0b84 687 (SCM port),
b380b885
MD
688 "Flush the specified output port, or the current output port if @var{port}\n"
689 "is omitted. The current output buffer contents are passed to the \n"
690 "underlying port implementation (e.g., in the case of fports, the\n"
691 "data will be written to the file and the output buffer will be cleared.)\n"
692 "It has no effect on an unbuffered port.\n\n"
693 "The return value is unspecified.")
1bbd0b84 694#define FUNC_NAME s_scm_force_output
0f2d19dd
JB
695{
696 if (SCM_UNBNDP (port))
3e877d15 697 port = scm_cur_outp;
0f2d19dd 698 else
78446828
MV
699 {
700 port = SCM_COERCE_OUTPORT (port);
3b3b36dd 701 SCM_VALIDATE_OPOUTPORT (1,port);
78446828 702 }
affc96b5 703 scm_flush (port);
ee149d03 704 return SCM_UNSPECIFIED;
0f2d19dd 705}
1bbd0b84 706#undef FUNC_NAME
0f2d19dd 707
a1ec6916 708SCM_DEFINE (scm_flush_all_ports, "flush-all-ports", 0, 0, 0,
1bbd0b84 709 (),
b380b885
MD
710 "Equivalent to calling @code{force-output} on\n"
711 "all open output ports. The return value is unspecified.")
1bbd0b84 712#define FUNC_NAME s_scm_flush_all_ports
89ea5b7c
GH
713{
714 int i;
715
716 for (i = 0; i < scm_port_table_size; i++)
717 {
ee149d03 718 if (SCM_OPOUTPORTP (scm_port_table[i]->port))
affc96b5 719 scm_flush (scm_port_table[i]->port);
89ea5b7c
GH
720 }
721 return SCM_UNSPECIFIED;
722}
1bbd0b84 723#undef FUNC_NAME
0f2d19dd 724
3b3b36dd 725SCM_DEFINE (scm_read_char, "read-char", 0, 1, 0,
1bbd0b84 726 (SCM port),
b380b885 727 "")
1bbd0b84 728#define FUNC_NAME s_scm_read_char
0f2d19dd
JB
729{
730 int c;
731 if (SCM_UNBNDP (port))
334341aa 732 port = scm_cur_inp;
3b3b36dd 733 SCM_VALIDATE_OPINPORT (1,port);
b7f3516f 734 c = scm_getc (port);
0f2d19dd
JB
735 if (EOF == c)
736 return SCM_EOF_VAL;
737 return SCM_MAKICHR (c);
738}
1bbd0b84 739#undef FUNC_NAME
0f2d19dd 740
5c070ca7 741/* this should only be called when the read buffer is empty. it
affc96b5 742 tries to refill the read buffer. it returns the first char from
5c070ca7 743 the port, which is either EOF or *(pt->read_pos). */
6c951427 744int
affc96b5 745scm_fill_input (SCM port)
6c951427 746{
283a1a0e
GH
747 scm_port *pt = SCM_PTAB_ENTRY (port);
748
6c951427
GH
749 if (pt->read_buf == pt->putback_buf)
750 {
751 /* finished reading put-back chars. */
752 pt->read_buf = pt->saved_read_buf;
753 pt->read_pos = pt->saved_read_pos;
754 pt->read_end = pt->saved_read_end;
755 pt->read_buf_size = pt->saved_read_buf_size;
756 if (pt->read_pos < pt->read_end)
5c070ca7 757 return *(pt->read_pos);
6c951427 758 }
affc96b5 759 return scm_ptobs[SCM_PTOBNUM (port)].fill_input (port);
6c951427
GH
760}
761
ee149d03 762int
a284e297 763scm_getc (SCM port)
0f2d19dd
JB
764{
765 int c;
840ae05d 766 scm_port *pt = SCM_PTAB_ENTRY (port);
ee149d03 767
840ae05d
JB
768 if (pt->rw_active == SCM_PORT_WRITE)
769 {
affc96b5
GH
770 /* may be marginally faster than calling scm_flush. */
771 scm_ptobs[SCM_PTOBNUM (port)].flush (port);
840ae05d 772 }
6c951427 773
5c070ca7
GH
774 if (pt->rw_random)
775 pt->rw_active = SCM_PORT_READ;
776
777 if (pt->read_pos >= pt->read_end)
ee149d03 778 {
affc96b5 779 if (scm_fill_input (port) == EOF)
5c070ca7 780 return EOF;
ee149d03
JB
781 }
782
5c070ca7 783 c = *(pt->read_pos++);
840ae05d 784
ee149d03
JB
785 if (c == '\n')
786 {
787 SCM_INCLINE (port);
788 }
789 else if (c == '\t')
790 {
791 SCM_TABCOL (port);
792 }
793 else
794 {
795 SCM_INCCOL (port);
796 }
797
798 return c;
0f2d19dd
JB
799}
800
ee149d03 801void
a284e297 802scm_putc (char c, SCM port)
ee149d03 803{
265e6a4d 804 scm_lfwrite (&c, 1, port);
ee149d03 805}
3cb988bd 806
ee149d03 807void
70d63753 808scm_puts (const char *s, SCM port)
3cb988bd 809{
265e6a4d 810 scm_lfwrite (s, strlen (s), port);
ee149d03 811}
3cb988bd 812
ee149d03 813void
70d63753 814scm_lfwrite (const char *ptr, scm_sizet size, SCM port)
ee149d03 815{
840ae05d 816 scm_port *pt = SCM_PTAB_ENTRY (port);
f12733c9 817 scm_ptob_descriptor *ptob = &scm_ptobs[SCM_PTOBNUM (port)];
3e2043c4 818
840ae05d 819 if (pt->rw_active == SCM_PORT_READ)
affc96b5 820 scm_end_input (port);
283a1a0e 821
31703ab8 822 ptob->write (port, ptr, size);
840ae05d
JB
823
824 if (pt->rw_random)
825 pt->rw_active = SCM_PORT_WRITE;
ee149d03 826}
3cb988bd 827
3cb988bd 828
ee149d03 829void
a284e297 830scm_flush (SCM port)
ee149d03
JB
831{
832 scm_sizet i = SCM_PTOBNUM (port);
affc96b5 833 (scm_ptobs[i].flush) (port);
ee149d03
JB
834}
835
283a1a0e 836void
a284e297 837scm_end_input (SCM port)
283a1a0e
GH
838{
839 int offset;
840 scm_port *pt = SCM_PTAB_ENTRY (port);
841
842 if (pt->read_buf == pt->putback_buf)
843 {
844 offset = pt->read_end - pt->read_pos;
845 pt->read_buf = pt->saved_read_buf;
846 pt->read_pos = pt->saved_read_pos;
847 pt->read_end = pt->saved_read_end;
848 pt->read_buf_size = pt->saved_read_buf_size;
849 }
850 else
851 offset = 0;
852
affc96b5 853 scm_ptobs[SCM_PTOBNUM (port)].end_input (port, offset);
283a1a0e
GH
854}
855
ee149d03
JB
856\f
857
858
859void
a284e297 860scm_ungetc (int c, SCM port)
ee149d03 861{
840ae05d
JB
862 scm_port *pt = SCM_PTAB_ENTRY (port);
863
6c951427
GH
864 if (pt->read_buf == pt->putback_buf)
865 /* already using the put-back buffer. */
866 {
867 /* enlarge putback_buf if necessary. */
868 if (pt->read_end == pt->read_buf + pt->read_buf_size
869 && pt->read_buf == pt->read_pos)
870 {
871 int new_size = pt->read_buf_size * 2;
872 unsigned char *tmp =
873 (unsigned char *) realloc (pt->putback_buf, new_size);
874
875 if (tmp == NULL)
876 scm_memory_error ("scm_ungetc");
877 pt->read_pos = pt->read_buf = pt->putback_buf = tmp;
878 pt->read_end = pt->read_buf + pt->read_buf_size;
879 pt->read_buf_size = pt->putback_buf_size = new_size;
880 }
881
882 /* shift any existing bytes to buffer + 1. */
883 if (pt->read_pos == pt->read_end)
884 pt->read_end = pt->read_buf + 1;
885 else if (pt->read_pos != pt->read_buf + 1)
886 {
887 int count = pt->read_end - pt->read_pos;
888
889 memmove (pt->read_buf + 1, pt->read_pos, count);
890 pt->read_end = pt->read_buf + 1 + count;
891 }
892
893 pt->read_pos = pt->read_buf;
894 }
895 else
896 /* switch to the put-back buffer. */
897 {
898 if (pt->putback_buf == NULL)
899 {
6e2e75db 900 pt->putback_buf = (char *) malloc (SCM_INITIAL_PUTBACK_BUF_SIZE);
6c951427
GH
901 if (pt->putback_buf == NULL)
902 scm_memory_error ("scm_ungetc");
903 pt->putback_buf_size = SCM_INITIAL_PUTBACK_BUF_SIZE;
904 }
905
906 pt->saved_read_buf = pt->read_buf;
907 pt->saved_read_pos = pt->read_pos;
908 pt->saved_read_end = pt->read_end;
909 pt->saved_read_buf_size = pt->read_buf_size;
910
911 pt->read_pos = pt->read_buf = pt->putback_buf;
912 pt->read_end = pt->read_buf + 1;
913 pt->read_buf_size = pt->putback_buf_size;
914 }
915
916 *pt->read_buf = c;
ee149d03 917
840ae05d
JB
918 if (pt->rw_random)
919 pt->rw_active = SCM_PORT_READ;
920
ee149d03
JB
921 if (c == '\n')
922 {
923 /* What should col be in this case?
924 * We'll leave it at -1.
925 */
926 SCM_LINUM (port) -= 1;
927 }
928 else
929 SCM_COL(port) -= 1;
930}
931
932
933void
70d63753 934scm_ungets (const char *s, int n, SCM port)
ee149d03
JB
935{
936 /* This is simple minded and inefficient, but unreading strings is
937 * probably not a common operation, and remember that line and
938 * column numbers have to be handled...
939 *
940 * Please feel free to write an optimized version!
941 */
942 while (n--)
943 scm_ungetc (s[n], port);
944}
945
946
3b3b36dd 947SCM_DEFINE (scm_peek_char, "peek-char", 0, 1, 0,
1bbd0b84 948 (SCM port),
b380b885 949 "")
1bbd0b84 950#define FUNC_NAME s_scm_peek_char
ee149d03
JB
951{
952 int c;
953 if (SCM_UNBNDP (port))
954 port = scm_cur_inp;
955 else
3b3b36dd 956 SCM_VALIDATE_OPINPORT (1,port);
ee149d03
JB
957 c = scm_getc (port);
958 if (EOF == c)
959 return SCM_EOF_VAL;
960 scm_ungetc (c, port);
961 return SCM_MAKICHR (c);
3cb988bd 962}
1bbd0b84 963#undef FUNC_NAME
3cb988bd 964
a1ec6916 965SCM_DEFINE (scm_unread_char, "unread-char", 2, 0, 0,
1bbd0b84 966 (SCM cobj, SCM port),
b380b885
MD
967 "Place @var{char} in @var{port} so that it will be read by the\n"
968 "next read operation. If called multiple times, the unread characters\n"
969 "will be read again in last-in first-out order. If @var{port} is\n"
970 "not supplied, the current input port is used.")
1bbd0b84 971#define FUNC_NAME s_scm_unread_char
0f2d19dd
JB
972{
973 int c;
974
9a8351bc 975 SCM_VALIDATE_ICHR (1,cobj);
0f2d19dd
JB
976 if (SCM_UNBNDP (port))
977 port = scm_cur_inp;
978 else
3b3b36dd 979 SCM_VALIDATE_OPINPORT (2,port);
0f2d19dd
JB
980
981 c = SCM_ICHR (cobj);
982
b7f3516f 983 scm_ungetc (c, port);
0f2d19dd
JB
984 return cobj;
985}
1bbd0b84 986#undef FUNC_NAME
0f2d19dd 987
a1ec6916 988SCM_DEFINE (scm_unread_string, "unread-string", 2, 0, 0,
1bbd0b84 989 (SCM str, SCM port),
b380b885
MD
990 "Place the string @var{str} in @var{port} so that its characters will be\n"
991 "read in subsequent read operations. If called multiple times, the\n"
992 "unread characters will be read again in last-in first-out order. If\n"
993 "@var{port} is not supplied, the current-input-port is used.")
1bbd0b84 994#define FUNC_NAME s_scm_unread_string
ee1e7e13 995{
3b3b36dd 996 SCM_VALIDATE_STRING (1,str);
ee1e7e13
MD
997 if (SCM_UNBNDP (port))
998 port = scm_cur_inp;
999 else
3b3b36dd 1000 SCM_VALIDATE_OPINPORT (2,port);
ee1e7e13 1001
d1c90db5 1002 scm_ungets (SCM_ROUCHARS (str), SCM_LENGTH (str), port);
ee1e7e13
MD
1003
1004 return str;
1005}
1bbd0b84 1006#undef FUNC_NAME
ee1e7e13 1007
a1ec6916 1008SCM_DEFINE (scm_seek, "seek", 3, 0, 0,
1bbd0b84 1009 (SCM object, SCM offset, SCM whence),
b380b885
MD
1010 "Sets the current position of @var{fd/port} to the integer @var{offset},\n"
1011 "which is interpreted according to the value of @var{whence}.\n\n"
1012 "One of the following variables should be supplied\n"
1013 "for @var{whence}:\n"
1014 "@defvar SEEK_SET\n"
1015 "Seek from the beginning of the file.\n"
1016 "@end defvar\n"
1017 "@defvar SEEK_CUR\n"
1018 "Seek from the current position.\n"
1019 "@end defvar\n"
1020 "@defvar SEEK_END\n"
1021 "Seek from the end of the file.\n"
1022 "@end defvar\n\n"
1023 "If @var{fd/port} is a file descriptor, the underlying system call is\n"
1024 "@code{lseek}. @var{port} may be a string port.\n\n"
1025 "The value returned is the new position in the file. This means that\n"
1026 "the current position of a port can be obtained using:\n"
1027 "@smalllisp\n"
1028 "(seek port 0 SEEK_CUR)\n"
1029 "@end smalllisp")
1bbd0b84 1030#define FUNC_NAME s_scm_seek
840ae05d
JB
1031{
1032 off_t off;
1033 off_t rv;
1034 int how;
1035
1036 object = SCM_COERCE_OUTPORT (object);
1037
1bbd0b84 1038 off = SCM_NUM2LONG (2,offset);
3b3b36dd 1039 SCM_VALIDATE_INUM_COPY (3,whence,how);
840ae05d 1040 if (how != SEEK_SET && how != SEEK_CUR && how != SEEK_END)
1bbd0b84 1041 SCM_OUT_OF_RANGE (3, whence);
0c95b57d 1042 if (SCM_OPPORTP (object))
840ae05d 1043 {
f12733c9 1044 scm_ptob_descriptor *ptob = scm_ptobs + SCM_PTOBNUM (object);
840ae05d
JB
1045
1046 if (!ptob->seek)
1bbd0b84
GB
1047 SCM_MISC_ERROR ("port is not seekable",
1048 scm_cons (object, SCM_EOL));
840ae05d 1049 else
7dcb364d 1050 rv = ptob->seek (object, off, how);
840ae05d
JB
1051 }
1052 else /* file descriptor?. */
1053 {
3b3b36dd 1054 SCM_VALIDATE_INUM (1,object);
840ae05d
JB
1055 rv = lseek (SCM_INUM (object), off, how);
1056 if (rv == -1)
1bbd0b84 1057 SCM_SYSERROR;
840ae05d
JB
1058 }
1059 return scm_long2num (rv);
1060}
1bbd0b84 1061#undef FUNC_NAME
840ae05d 1062
a1ec6916 1063SCM_DEFINE (scm_truncate_file, "truncate-file", 1, 1, 0,
1bbd0b84 1064 (SCM object, SCM length),
b380b885
MD
1065 "Truncates the object referred to by @var{obj} to at most @var{size} bytes.\n"
1066 "@var{obj} can be a string containing a file name or an integer file\n"
1067 "descriptor or a port. @var{size} may be omitted if @var{obj} is not\n"
1068 "a file name, in which case the truncation occurs at the current port.\n"
1069 "position.\n\n"
1070 "The return value is unspecified.")
1bbd0b84 1071#define FUNC_NAME s_scm_truncate_file
840ae05d 1072{
69bc9ff3
GH
1073 int rv;
1074 off_t c_length;
1075
1076 /* object can be a port, fdes or filename. */
840ae05d 1077
840ae05d
JB
1078 if (SCM_UNBNDP (length))
1079 {
69bc9ff3 1080 /* must supply length if object is a filename. */
0c95b57d 1081 if (SCM_ROSTRINGP (object))
c1bfcf60 1082 SCM_MISC_ERROR("must supply length if OBJECT is a filename",SCM_EOL);
69bc9ff3 1083
c94577b4 1084 length = scm_seek (object, SCM_INUM0, SCM_MAKINUM (SEEK_CUR));
840ae05d 1085 }
1bbd0b84 1086 c_length = SCM_NUM2LONG (2,length);
69bc9ff3 1087 if (c_length < 0)
1bbd0b84 1088 SCM_MISC_ERROR ("negative offset", SCM_EOL);
3fe6190f 1089
69bc9ff3
GH
1090 object = SCM_COERCE_OUTPORT (object);
1091 if (SCM_INUMP (object))
1092 {
1093 SCM_SYSCALL (rv = ftruncate (SCM_INUM (object), c_length));
1094 }
0c95b57d 1095 else if (SCM_OPOUTPORTP (object))
69bc9ff3
GH
1096 {
1097 scm_port *pt = SCM_PTAB_ENTRY (object);
f12733c9 1098 scm_ptob_descriptor *ptob = scm_ptobs + SCM_PTOBNUM (object);
69bc9ff3 1099
affc96b5 1100 if (!ptob->truncate)
1bbd0b84 1101 SCM_MISC_ERROR ("port is not truncatable", SCM_EOL);
69bc9ff3 1102 if (pt->rw_active == SCM_PORT_READ)
affc96b5 1103 scm_end_input (object);
69bc9ff3 1104 else if (pt->rw_active == SCM_PORT_WRITE)
affc96b5 1105 ptob->flush (object);
69bc9ff3 1106
affc96b5 1107 ptob->truncate (object, c_length);
69bc9ff3
GH
1108 rv = 0;
1109 }
1110 else
1111 {
3b3b36dd 1112 SCM_VALIDATE_ROSTRING (1,object);
69bc9ff3
GH
1113 SCM_COERCE_SUBSTR (object);
1114 SCM_SYSCALL (rv = truncate (SCM_ROCHARS (object), c_length));
1115 }
1116 if (rv == -1)
1bbd0b84 1117 SCM_SYSERROR;
840ae05d
JB
1118 return SCM_UNSPECIFIED;
1119}
1bbd0b84 1120#undef FUNC_NAME
840ae05d 1121
a1ec6916 1122SCM_DEFINE (scm_port_line, "port-line", 1, 0, 0,
1bbd0b84 1123 (SCM port),
b380b885 1124 "")
1bbd0b84 1125#define FUNC_NAME s_scm_port_line
0f2d19dd 1126{
78446828 1127 port = SCM_COERCE_OUTPORT (port);
3b3b36dd 1128 SCM_VALIDATE_OPENPORT (1,port);
360fc44c 1129 return SCM_MAKINUM (SCM_LINUM (port));
0f2d19dd 1130}
1bbd0b84 1131#undef FUNC_NAME
0f2d19dd 1132
a1ec6916 1133SCM_DEFINE (scm_set_port_line_x, "set-port-line!", 2, 0, 0,
1bbd0b84 1134 (SCM port, SCM line),
b380b885 1135 "")
1bbd0b84 1136#define FUNC_NAME s_scm_set_port_line_x
d043d8c2 1137{
360fc44c 1138 port = SCM_COERCE_OUTPORT (port);
3b3b36dd
GB
1139 SCM_VALIDATE_OPENPORT (1,port);
1140 SCM_VALIDATE_INUM (2,line);
d043d8c2
MD
1141 return SCM_PTAB_ENTRY (port)->line_number = SCM_INUM (line);
1142}
1bbd0b84 1143#undef FUNC_NAME
d043d8c2 1144
a1ec6916 1145SCM_DEFINE (scm_port_column, "port-column", 1, 0, 0,
1bbd0b84 1146 (SCM port),
b380b885
MD
1147 "@deffnx primitive port-line [input-port]\n"
1148 "Return the current column number or line number of @var{input-port},\n"
1149 "using the current input port if none is specified. If the number is\n"
1150 "unknown, the result is #f. Otherwise, the result is a 0-origin integer\n"
1151 "- i.e. the first character of the first line is line 0, column 0.\n"
1152 "(However, when you display a file position, for example in an error\n"
1153 "message, we recommand you add 1 to get 1-origin integers. This is\n"
1154 "because lines and column numbers traditionally start with 1, and that is\n"
1155 "what non-programmers will find most natural.)")
1bbd0b84 1156#define FUNC_NAME s_scm_port_column
0f2d19dd 1157{
78446828 1158 port = SCM_COERCE_OUTPORT (port);
3b3b36dd 1159 SCM_VALIDATE_OPENPORT (1,port);
360fc44c 1160 return SCM_MAKINUM (SCM_COL (port));
0f2d19dd 1161}
1bbd0b84 1162#undef FUNC_NAME
0f2d19dd 1163
a1ec6916 1164SCM_DEFINE (scm_set_port_column_x, "set-port-column!", 2, 0, 0,
1bbd0b84 1165 (SCM port, SCM column),
b380b885
MD
1166 "@deffnx primitive set-port-line! [input-port] line\n"
1167 "Set the current column or line number of @var{input-port}, using the\n"
1168 "current input port if none is specified.")
1bbd0b84 1169#define FUNC_NAME s_scm_set_port_column_x
d043d8c2 1170{
360fc44c 1171 port = SCM_COERCE_OUTPORT (port);
3b3b36dd
GB
1172 SCM_VALIDATE_OPENPORT (1,port);
1173 SCM_VALIDATE_INUM (2,column);
d043d8c2
MD
1174 return SCM_PTAB_ENTRY (port)->column_number = SCM_INUM (column);
1175}
1bbd0b84 1176#undef FUNC_NAME
d043d8c2 1177
a1ec6916 1178SCM_DEFINE (scm_port_filename, "port-filename", 1, 0, 0,
1bbd0b84 1179 (SCM port),
b380b885
MD
1180 "Return the filename associated with @var{port}. This function returns\n"
1181 "the strings "standard input", "standard output" and "standard error"
4079f87e 1182when called on the current input, output and error ports respectively.")
1bbd0b84 1183#define FUNC_NAME s_scm_port_filename
0f2d19dd 1184{
78446828 1185 port = SCM_COERCE_OUTPORT (port);
3b3b36dd 1186 SCM_VALIDATE_OPENPORT (1,port);
360fc44c 1187 return SCM_PTAB_ENTRY (port)->file_name;
0f2d19dd 1188}
1bbd0b84 1189#undef FUNC_NAME
0f2d19dd 1190
a1ec6916 1191SCM_DEFINE (scm_set_port_filename_x, "set-port-filename!", 2, 0, 0,
1bbd0b84 1192 (SCM port, SCM filename),
b380b885
MD
1193 "Change the filename associated with @var{port}, using the current input\n"
1194 "port if none is specified. Note that this does not change the port's\n"
1195 "source of data, but only the value that is returned by\n"
1196 "@code{port-filename} and reported in diagnostic output.")
1bbd0b84 1197#define FUNC_NAME s_scm_set_port_filename_x
d14af9f2 1198{
360fc44c 1199 port = SCM_COERCE_OUTPORT (port);
3b3b36dd 1200 SCM_VALIDATE_OPENPORT (1,port);
360fc44c 1201 /* We allow the user to set the filename to whatever he likes. */
d14af9f2
MD
1202 return SCM_PTAB_ENTRY (port)->file_name = filename;
1203}
1bbd0b84 1204#undef FUNC_NAME
d14af9f2 1205
0f2d19dd
JB
1206#ifndef ttyname
1207extern char * ttyname();
1208#endif
1209
f12733c9
MD
1210void
1211scm_print_port_mode (SCM exp, SCM port)
1212{
1213 scm_puts (SCM_CLOSEDP (exp)
1214 ? "closed: "
1215 : (SCM_RDNG & SCM_CAR (exp)
1216 ? (SCM_WRTNG & SCM_CAR (exp)
1217 ? "input-output: "
1218 : "input: ")
1219 : (SCM_WRTNG & SCM_CAR (exp)
1220 ? "output: "
1221 : "bogus: ")),
1222 port);
1223}
1cc91f1b 1224
f12733c9
MD
1225int
1226scm_port_print (SCM exp, SCM port, scm_print_state *pstate)
0f2d19dd 1227{
f12733c9
MD
1228 char *type = SCM_PTOBNAME (SCM_PTOBNUM (exp));
1229 if (!type)
1230 type = "port";
b7f3516f 1231 scm_puts ("#<", port);
f12733c9 1232 scm_print_port_mode (exp, port);
b7f3516f
TT
1233 scm_puts (type, port);
1234 scm_putc (' ', port);
f12733c9 1235 scm_intprint (SCM_CDR (exp), 16, port);
b7f3516f 1236 scm_putc ('>', port);
f12733c9 1237 return 1;
0f2d19dd
JB
1238}
1239
f12733c9
MD
1240extern void scm_make_fptob ();
1241extern void scm_make_stptob ();
1242extern void scm_make_sfptob ();
1cc91f1b 1243
0f2d19dd
JB
1244void
1245scm_ports_prehistory ()
0f2d19dd
JB
1246{
1247 scm_numptob = 0;
f12733c9 1248 scm_ptobs = (scm_ptob_descriptor *) malloc (sizeof (scm_ptob_descriptor));
0f2d19dd
JB
1249
1250 /* WARNING: These scm_newptob calls must be done in this order.
1251 * They must agree with the port declarations in tags.h.
1252 */
f12733c9
MD
1253 /* scm_tc16_fport = */ scm_make_fptob ();
1254 /* scm_tc16_pipe was here */ scm_make_fptob (); /* dummy. */
1255 /* scm_tc16_strport = */ scm_make_stptob ();
1256 /* scm_tc16_sfport = */ scm_make_sfptob ();
0f2d19dd 1257}
0f2d19dd
JB
1258
1259\f
ee149d03 1260
d68fee48 1261/* Void ports. */
0f2d19dd 1262
f12733c9 1263long scm_tc16_void_port = 0;
0f2d19dd 1264
ee149d03 1265static void
0f88a8f3 1266flush_void_port (SCM port)
0f2d19dd 1267{
3cb988bd 1268}
1cc91f1b 1269
283a1a0e 1270static void
affc96b5 1271end_input_void_port (SCM port, int offset)
283a1a0e
GH
1272{
1273}
1274
31703ab8 1275static void
8aa011a1 1276write_void_port (SCM port, const void *data, size_t size)
31703ab8
GH
1277{
1278}
1279
0f2d19dd 1280SCM
a284e297 1281scm_void_port (char *mode_str)
0f2d19dd
JB
1282{
1283 int mode_bits;
1284 SCM answer;
840ae05d 1285 scm_port * pt;
0f2d19dd
JB
1286
1287 SCM_NEWCELL (answer);
1288 SCM_DEFER_INTS;
1289 mode_bits = scm_mode_bits (mode_str);
1290 pt = scm_add_to_port_table (answer);
0f2d19dd 1291 SCM_SETPTAB_ENTRY (answer, pt);
ee149d03
JB
1292 SCM_SETSTREAM (answer, 0);
1293 SCM_SETCAR (answer, scm_tc16_void_port | mode_bits);
0f2d19dd
JB
1294 SCM_ALLOW_INTS;
1295 return answer;
1296}
1297
1298
a1ec6916 1299SCM_DEFINE (scm_sys_make_void_port, "%make-void-port", 1, 0, 0,
1bbd0b84 1300 (SCM mode),
b380b885
MD
1301 "Create and return a new void port. The @var{mode} argument describes\n"
1302 "the input/output modes for this port; for a description, see the\n"
1303 "documentation for @code{open-file} in @ref{File Ports}.")
1bbd0b84 1304#define FUNC_NAME s_scm_sys_make_void_port
0f2d19dd 1305{
3b3b36dd 1306 SCM_VALIDATE_ROSTRING (1,mode);
89958ad0 1307 SCM_COERCE_SUBSTR (mode);
0f2d19dd
JB
1308 return scm_void_port (SCM_ROCHARS (mode));
1309}
1bbd0b84 1310#undef FUNC_NAME
0f2d19dd 1311
0f2d19dd 1312\f
89545eba 1313/* Initialization. */
1cc91f1b 1314
0f2d19dd
JB
1315void
1316scm_init_ports ()
0f2d19dd 1317{
840ae05d
JB
1318 /* lseek() symbols. */
1319 scm_sysintern ("SEEK_SET", SCM_MAKINUM (SEEK_SET));
1320 scm_sysintern ("SEEK_CUR", SCM_MAKINUM (SEEK_CUR));
1321 scm_sysintern ("SEEK_END", SCM_MAKINUM (SEEK_END));
1322
affc96b5 1323 scm_tc16_void_port = scm_make_port_type ("void", 0, write_void_port);
0f2d19dd
JB
1324#include "ports.x"
1325}