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