port locking refactor
[bpt/guile.git] / libguile / ports.h
CommitLineData
0f2d19dd
JB
1/* classes: h_files */
2
22a52da1
DH
3#ifndef SCM_PORTS_H
4#define SCM_PORTS_H
8c494e99 5
a9178715
LC
6/* Copyright (C) 1995, 1996, 1997, 1998, 1999, 2000, 2001, 2003, 2004,
7 * 2006, 2008, 2009, 2010, 2011 Free Software Foundation, Inc.
8c494e99 8 *
73be1d9e 9 * This library is free software; you can redistribute it and/or
53befeb7
NJ
10 * modify it under the terms of the GNU Lesser General Public License
11 * as published by the Free Software Foundation; either version 3 of
12 * the License, or (at your option) any later version.
8c494e99 13 *
53befeb7
NJ
14 * This library is distributed in the hope that it will be useful, but
15 * WITHOUT ANY WARRANTY; without even the implied warranty of
73be1d9e
MV
16 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
17 * Lesser General Public License for more details.
8c494e99 18 *
73be1d9e
MV
19 * You should have received a copy of the GNU Lesser General Public
20 * License along with this library; if not, write to the Free Software
53befeb7
NJ
21 * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
22 * 02110-1301 USA
73be1d9e 23 */
d3a6bc94 24
0f2d19dd 25\f
8c494e99 26
b4309c3c 27#include "libguile/__scm.h"
0f2d19dd 28
fca14149
AW
29#include <stdio.h>
30#include <string.h>
0c247c33 31#include <unistd.h>
fca14149
AW
32#include "libguile/gc.h"
33#include "libguile/tags.h"
34#include "libguile/error.h"
e0d86ad2 35#include "libguile/print.h"
78446828 36#include "libguile/struct.h"
b9ad392e 37#include "libguile/threads.h"
889975e5 38#include "libguile/strings.h"
acdb12da 39
0f2d19dd
JB
40\f
41
6c951427 42#define SCM_INITIAL_PUTBACK_BUF_SIZE 4
0855ef71 43
61e452ba 44/* values for the rw_active flag. */
92c2555f 45typedef enum scm_t_port_rw_active {
61e452ba
JB
46 SCM_PORT_NEITHER = 0,
47 SCM_PORT_READ = 1,
48 SCM_PORT_WRITE = 2
92c2555f 49} scm_t_port_rw_active;
61e452ba 50
840ae05d
JB
51/* C representation of a Scheme port. */
52
53typedef struct
0f2d19dd 54{
ee149d03 55 SCM port; /* Link back to the port object. */
92c0ebac 56 scm_i_pthread_mutex_t *lock; /* A recursive lock for this port. */
30b126d2 57
0f2d19dd
JB
58 int revealed; /* 0 not revealed, > 1 revealed.
59 * Revealed ports do not get GC'd.
60 */
74a16888 61 /* data for the underlying port implementation as a raw C value. */
92c2555f 62 scm_t_bits stream;
0f2d19dd 63
0855ef71 64 SCM file_name; /* debugging support. */
1be6b49c 65 long line_number; /* debugging support. */
ebf7394e 66 int column_number; /* debugging support. */
0855ef71 67
889975e5
MG
68 /* Character encoding support */
69 char *encoding;
70 scm_t_string_failed_conversion_handler ilseq_handler;
71
ee149d03
JB
72 /* port buffers. the buffer(s) are set up for all ports.
73 in the case of string ports, the buffer is the string itself.
74 in the case of unbuffered file ports, the buffer is a
75 single char: shortbuf. */
76
77 /* this buffer is filled from read_buf to read_end using the ptob
78 buffer_fill. then input requests are taken from read_pos until
79 it reaches read_end. */
80
81 unsigned char *read_buf; /* buffer start. */
840ae05d 82 const unsigned char *read_pos;/* the next unread char. */
ee149d03 83 unsigned char *read_end; /* pointer to last buffered char + 1. */
f1ce9199 84 scm_t_off read_buf_size; /* size of the buffer. */
ee149d03 85
6c951427
GH
86 /* when chars are put back into the buffer, e.g., using peek-char or
87 unread-string, the read-buffer pointers are switched to cbuf.
88 the original pointers are saved here and restored when the put-back
89 chars have been consumed. */
90 unsigned char *saved_read_buf;
91 const unsigned char *saved_read_pos;
92 unsigned char *saved_read_end;
f1ce9199 93 scm_t_off saved_read_buf_size;
6c951427 94
ee149d03
JB
95 /* write requests are saved into this buffer at write_pos until it
96 reaches write_buf + write_buf_size, then the ptob flush is
97 called. */
98
6c951427 99 unsigned char *write_buf; /* buffer start. */
ee149d03
JB
100 unsigned char *write_pos; /* pointer to last buffered char + 1. */
101 unsigned char *write_end; /* pointer to end of buffer + 1. */
f1ce9199 102 scm_t_off write_buf_size; /* size of the buffer. */
ee149d03
JB
103
104 unsigned char shortbuf; /* buffer for "unbuffered" streams. */
105
0de97b83
GH
106 int rw_random; /* true if the port is random access.
107 implies that the buffers must be
108 flushed before switching between
109 reading and writing, seeking, etc. */
110
92c2555f 111 scm_t_port_rw_active rw_active; /* for random access ports,
1be6b49c
ML
112 indicates which of the buffers
113 is currently in use. can be
114 SCM_PORT_WRITE, SCM_PORT_READ,
115 or SCM_PORT_NEITHER. */
ee149d03 116
61e452ba 117
6c951427
GH
118 /* a buffer for un-read chars and strings. */
119 unsigned char *putback_buf;
1be6b49c 120 size_t putback_buf_size; /* allocated size of putback_buf. */
f4bc4e59
LC
121
122 /* input/output iconv conversion descriptors */
123 void *input_cd;
124 void *output_cd;
92c2555f 125} scm_t_port;
840ae05d 126
5dbc6c06 127
2721f918 128SCM_INTERNAL SCM scm_i_port_weak_set;
5dbc6c06 129
0f2d19dd 130
6fe692e9 131#define SCM_READ_BUFFER_EMPTY_P(c_port) (c_port->read_pos >= c_port->read_end)
0f2d19dd
JB
132
133\f
134
bc36d050 135#define SCM_EOF_OBJECT_P(x) (scm_is_eq ((x), SCM_EOF_VAL))
0c32d76c 136
0f2d19dd 137/* PORT FLAGS
dbece3a2 138 * A set of flags characterizes a port.
571031dc
JB
139 * Note that we reserve the bits 1 << 24 and above for use by the
140 * routines in the port's scm_ptobfuns structure.
0f2d19dd
JB
141 */
142#define SCM_OPN (1L<<16) /* Is the port open? */
143#define SCM_RDNG (2L<<16) /* Is it a readable port? */
144#define SCM_WRTNG (4L<<16) /* Is it writable? */
ee149d03 145#define SCM_BUF0 (8L<<16) /* Is it unbuffered? */
ee149d03 146#define SCM_BUFLINE (64L<<16) /* Is it line-buffered? */
0f2d19dd 147
dc7da0be
AW
148#define SCM_PORTP(x) (SCM_HAS_TYP7 (x, scm_tc7_port))
149#define SCM_OPPORTP(x) (SCM_PORTP (x) && (SCM_CELL_WORD_0 (x) & SCM_OPN))
150#define SCM_INPUT_PORT_P(x) (SCM_PORTP (x) && (SCM_CELL_WORD_0 (x) & SCM_RDNG))
151#define SCM_OUTPUT_PORT_P(x) (SCM_PORTP (x) && (SCM_CELL_WORD_0 (x) & SCM_WRTNG))
152#define SCM_OPINPORTP(x) (SCM_OPPORTP (x) && SCM_INPUT_PORT_P (x))
153#define SCM_OPOUTPORTP(x) (SCM_OPPORTP (x) && SCM_OUTPUT_PORT_P (x))
154#define SCM_OPENP(x) (SCM_OPPORTP (x))
155#define SCM_CLOSEDP(x) (!SCM_OPENP (x))
22a52da1
DH
156#define SCM_CLR_PORT_OPEN_FLAG(p) \
157 SCM_SET_CELL_WORD_0 ((p), SCM_CELL_WORD_0 (p) & ~SCM_OPN)
843524cc 158
92c2555f 159#define SCM_PTAB_ENTRY(x) ((scm_t_port *) SCM_CELL_WORD_1 (x))
62bd5d66 160#define SCM_PORT_DESCRIPTOR(port) ((scm_t_ptob_descriptor *) SCM_CELL_WORD_2 (port))
34d19ef6 161#define SCM_SETPTAB_ENTRY(x, ent) (SCM_SET_CELL_WORD_1 ((x), (scm_t_bits) (ent)))
843524cc 162#define SCM_STREAM(x) (SCM_PTAB_ENTRY(x)->stream)
34d19ef6 163#define SCM_SETSTREAM(x, s) (SCM_PTAB_ENTRY(x)->stream = (scm_t_bits) (s))
843524cc 164#define SCM_FILENAME(x) (SCM_PTAB_ENTRY(x)->file_name)
b24b5e13 165#define SCM_SET_FILENAME(x, n) (SCM_PTAB_ENTRY(x)->file_name = (n))
843524cc
DH
166#define SCM_LINUM(x) (SCM_PTAB_ENTRY(x)->line_number)
167#define SCM_COL(x) (SCM_PTAB_ENTRY(x)->column_number)
168#define SCM_REVEALED(x) (SCM_PTAB_ENTRY(x)->revealed)
34d19ef6 169#define SCM_SETREVEALED(x, s) (SCM_PTAB_ENTRY(x)->revealed = (s))
0f2d19dd 170
b0799290
MG
171#define SCM_INCLINE(port) do {SCM_LINUM (port) += 1; SCM_COL (port) = 0;} while (0)
172#define SCM_ZEROCOL(port) do {SCM_COL (port) = 0;} while (0)
173#define SCM_INCCOL(port) do {SCM_COL (port) += 1;} while (0)
174#define SCM_DECCOL(port) do {if (SCM_COL (port) > 0) SCM_COL (port) -= 1;} while (0)
175#define SCM_TABCOL(port) do {SCM_COL (port) += 8 - SCM_COL (port) % 8;} while (0)
0f2d19dd 176
0953b549
LC
177/* Maximum number of port types. */
178#define SCM_I_MAX_PORT_TYPE_COUNT 256
179
0f2d19dd
JB
180\f
181
affc96b5 182/* port-type description. */
92c2555f 183typedef struct scm_t_ptob_descriptor
0f82baf6 184{
f12733c9 185 char *name;
0c0669cc 186 SCM (*mark) (SCM);
1be6b49c 187 size_t (*free) (SCM);
0c0669cc
JB
188 int (*print) (SCM exp, SCM port, scm_print_state *pstate);
189 SCM (*equalp) (SCM, SCM);
affc96b5
GH
190 int (*close) (SCM port);
191
8aa011a1 192 void (*write) (SCM port, const void *data, size_t size);
affc96b5
GH
193 void (*flush) (SCM port);
194
195 void (*end_input) (SCM port, int offset);
196 int (*fill_input) (SCM port);
197 int (*input_waiting) (SCM port);
198
f1ce9199
LC
199 scm_t_off (*seek) (SCM port, scm_t_off OFFSET, int WHENCE);
200 void (*truncate) (SCM port, scm_t_off length);
affc96b5 201
92c2555f 202} scm_t_ptob_descriptor;
1be6b49c 203
12a8b769
DH
204#define SCM_TC2PTOBNUM(x) (0x0ff & ((x) >> 8))
205#define SCM_PTOBNUM(x) (SCM_TC2PTOBNUM (SCM_CELL_TYPE (x)))
f12733c9 206/* SCM_PTOBNAME can be 0 if name is missing */
62bd5d66 207#define SCM_PTOBNAME(ptobnum) (scm_c_port_type_ref (ptobnum)->name)
0f2d19dd 208
a535e9f5 209/* Port types, and their vtables. */
62bd5d66
AW
210SCM_INTERNAL long scm_c_num_port_types (void);
211SCM_API scm_t_ptob_descriptor* scm_c_port_type_ref (long ptobnum);
212SCM_API long scm_c_port_type_add_x (scm_t_ptob_descriptor *desc);
33b001fd
MV
213SCM_API scm_t_bits scm_make_port_type (char *name,
214 int (*fill_input) (SCM port),
215 void (*write) (SCM port,
216 const void *data,
217 size_t size));
23f2b9a3
KR
218SCM_API void scm_set_port_mark (scm_t_bits tc, SCM (*mark) (SCM));
219SCM_API void scm_set_port_free (scm_t_bits tc, size_t (*free) (SCM));
220SCM_API void scm_set_port_print (scm_t_bits tc,
33b001fd
MV
221 int (*print) (SCM exp,
222 SCM port,
223 scm_print_state *pstate));
23f2b9a3
KR
224SCM_API void scm_set_port_equalp (scm_t_bits tc, SCM (*equalp) (SCM, SCM));
225SCM_API void scm_set_port_close (scm_t_bits tc, int (*close) (SCM));
33b001fd 226
62bd5d66 227SCM_API void scm_set_port_flush (scm_t_bits tc, void (*flush) (SCM port));
23f2b9a3 228SCM_API void scm_set_port_end_input (scm_t_bits tc,
62bd5d66
AW
229 void (*end_input) (SCM port,
230 int offset));
23f2b9a3 231SCM_API void scm_set_port_seek (scm_t_bits tc,
f1ce9199
LC
232 scm_t_off (*seek) (SCM port,
233 scm_t_off OFFSET,
234 int WHENCE));
23f2b9a3 235SCM_API void scm_set_port_truncate (scm_t_bits tc,
33b001fd 236 void (*truncate) (SCM port,
f1ce9199 237 scm_t_off length));
23f2b9a3 238SCM_API void scm_set_port_input_waiting (scm_t_bits tc, int (*input_waiting) (SCM));
a535e9f5
AW
239
240/* The input, output, error, and load ports. */
33b001fd
MV
241SCM_API SCM scm_current_input_port (void);
242SCM_API SCM scm_current_output_port (void);
243SCM_API SCM scm_current_error_port (void);
244SCM_API SCM scm_current_load_port (void);
245SCM_API SCM scm_set_current_input_port (SCM port);
246SCM_API SCM scm_set_current_output_port (SCM port);
247SCM_API SCM scm_set_current_error_port (SCM port);
661ae7ab
MV
248SCM_API void scm_dynwind_current_input_port (SCM port);
249SCM_API void scm_dynwind_current_output_port (SCM port);
250SCM_API void scm_dynwind_current_error_port (SCM port);
a535e9f5
AW
251SCM_INTERNAL void scm_i_dynwind_current_load_port (SCM port);
252
253/* Mode bits. */
254SCM_INTERNAL long scm_i_mode_bits (SCM modes);
255SCM_API long scm_mode_bits (char *modes);
256SCM_API SCM scm_port_mode (SCM port);
2721f918 257
a535e9f5 258/* Low-level constructors. */
2721f918
AW
259SCM_API SCM
260scm_c_make_port_with_encoding (scm_t_bits tag,
261 unsigned long mode_bits,
262 const char *encoding,
263 scm_t_string_failed_conversion_handler handler,
264 scm_t_bits stream);
265SCM_API SCM scm_c_make_port (scm_t_bits tag, unsigned long mode_bits,
266 scm_t_bits stream);
891702ea 267SCM_API SCM scm_new_port_table_entry (scm_t_bits tag);
2721f918 268
a535e9f5
AW
269/* Predicates. */
270SCM_API SCM scm_port_p (SCM x);
271SCM_API SCM scm_input_port_p (SCM x);
272SCM_API SCM scm_output_port_p (SCM x);
273SCM_API SCM scm_port_closed_p (SCM port);
274SCM_API SCM scm_eof_object_p (SCM x);
275
276/* Closing ports. */
277SCM_API SCM scm_close_port (SCM port);
278SCM_API SCM scm_close_input_port (SCM port);
279SCM_API SCM scm_close_output_port (SCM port);
280
281/* Encoding characters to byte streams, and decoding byte streams to
282 characters. */
283SCM_INTERNAL const char *scm_i_default_port_encoding (void);
284SCM_INTERNAL void scm_i_set_default_port_encoding (const char *);
285SCM_INTERNAL void scm_i_set_port_encoding_x (SCM port, const char *str);
286SCM_API SCM scm_port_encoding (SCM port);
287SCM_API SCM scm_set_port_encoding_x (SCM port, SCM encoding);
288SCM_INTERNAL scm_t_string_failed_conversion_handler scm_i_get_conversion_strategy (SCM port);
289SCM_INTERNAL void scm_i_set_conversion_strategy_x (SCM port,
290 scm_t_string_failed_conversion_handler h);
291SCM_API SCM scm_port_conversion_strategy (SCM port);
292SCM_API SCM scm_set_port_conversion_strategy_x (SCM port, SCM behavior);
293
294/* Acquiring and releasing the port lock. */
14dcb5cc 295SCM_API void scm_dynwind_lock_port (SCM port);
92c0ebac
AW
296SCM_INLINE int scm_c_lock_port (SCM port, scm_i_pthread_mutex_t **lock);
297SCM_INLINE int scm_c_try_lock_port (SCM port, scm_i_pthread_mutex_t **lock);
30b126d2 298
19b8d12b 299/* Revealed counts. */
33b001fd
MV
300SCM_API int scm_revealed_count (SCM port);
301SCM_API SCM scm_port_revealed (SCM port);
302SCM_API SCM scm_set_port_revealed_x (SCM port, SCM rcount);
b262d306 303SCM_API SCM scm_adjust_port_revealed_x (SCM port, SCM addend);
a535e9f5
AW
304
305/* Input. */
0d959103 306SCM_API int scm_get_byte_or_eof (SCM port);
0d959103 307SCM_INLINE int scm_get_byte_or_eof_unlocked (SCM port);
c932ce0b 308SCM_API int scm_peek_byte_or_eof (SCM port);
0d959103 309SCM_INLINE int scm_peek_byte_or_eof_unlocked (SCM port);
33b001fd 310SCM_API size_t scm_c_read (SCM port, void *buffer, size_t size);
be632904 311SCM_API size_t scm_c_read_unlocked (SCM port, void *buffer, size_t size);
a535e9f5 312SCM_API scm_t_wchar scm_getc (SCM port);
be632904 313SCM_API scm_t_wchar scm_getc_unlocked (SCM port);
a535e9f5
AW
314SCM_API SCM scm_read_char (SCM port);
315
316/* Pushback. */
317SCM_INTERNAL void scm_unget_byte (int c, SCM port);
c932ce0b 318SCM_INTERNAL void scm_unget_byte_unlocked (int c, SCM port);
a535e9f5 319SCM_API void scm_ungetc (scm_t_wchar c, SCM port);
c932ce0b 320SCM_API void scm_ungetc_unlocked (scm_t_wchar c, SCM port);
a535e9f5 321SCM_API void scm_ungets (const char *s, int n, SCM port);
c932ce0b 322SCM_API void scm_ungets_unlocked (const char *s, int n, SCM port);
19b8d12b 323SCM_API SCM scm_peek_char (SCM port);
a535e9f5
AW
324SCM_API SCM scm_unread_char (SCM cobj, SCM port);
325SCM_API SCM scm_unread_string (SCM str, SCM port);
326
327/* Manipulating the buffers. */
328SCM_API void scm_port_non_buffer (scm_t_port *pt);
329SCM_API int scm_fill_input (SCM port);
4251ae2e 330SCM_API int scm_fill_input_unlocked (SCM port);
a535e9f5
AW
331SCM_INTERNAL size_t scm_take_from_input_buffers (SCM port, char *dest, size_t read_len);
332SCM_API SCM scm_drain_input (SCM port);
333SCM_API void scm_end_input (SCM port);
4251ae2e 334SCM_API void scm_end_input_unlocked (SCM port);
a535e9f5
AW
335SCM_API SCM scm_force_output (SCM port);
336SCM_API void scm_flush (SCM port);
4251ae2e 337SCM_API void scm_flush_unlocked (SCM port);
a535e9f5
AW
338
339/* Output. */
0607ebbf
AW
340SCM_API void scm_putc (char c, SCM port);
341SCM_INLINE void scm_putc_unlocked (char c, SCM port);
342SCM_API void scm_puts (const char *str_data, SCM port);
343SCM_INLINE void scm_puts_unlocked (const char *str_data, SCM port);
33b001fd 344SCM_API void scm_c_write (SCM port, const void *buffer, size_t size);
f209aeee 345SCM_API void scm_c_write_unlocked (SCM port, const void *buffer, size_t size);
33b001fd 346SCM_API void scm_lfwrite (const char *ptr, size_t size, SCM port);
f209aeee 347SCM_API void scm_lfwrite_unlocked (const char *ptr, size_t size, SCM port);
9c44cd45
MG
348SCM_INTERNAL void scm_lfwrite_substr (SCM str, size_t start, size_t end,
349 SCM port);
a535e9f5
AW
350
351/* Querying and setting positions, and character availability. */
352SCM_API SCM scm_char_ready_p (SCM port);
33b001fd
MV
353SCM_API SCM scm_seek (SCM object, SCM offset, SCM whence);
354SCM_API SCM scm_truncate_file (SCM object, SCM length);
355SCM_API SCM scm_port_line (SCM port);
356SCM_API SCM scm_set_port_line_x (SCM port, SCM line);
357SCM_API SCM scm_port_column (SCM port);
358SCM_API SCM scm_set_port_column_x (SCM port, SCM line);
359SCM_API SCM scm_port_filename (SCM port);
360SCM_API SCM scm_set_port_filename_x (SCM port, SCM filename);
a535e9f5
AW
361
362/* Implementation helpers for port printing functions. */
33b001fd
MV
363SCM_API int scm_port_print (SCM exp, SCM port, scm_print_state *);
364SCM_API void scm_print_port_mode (SCM exp, SCM port);
a535e9f5
AW
365
366/* Iterating over all ports. */
367SCM_API SCM scm_port_for_each (SCM proc);
368SCM_API void scm_c_port_for_each (void (*proc)(void *data, SCM p), void *data);
369SCM_API SCM scm_flush_all_ports (void);
370
371/* Void ports. */
33b001fd
MV
372SCM_API SCM scm_void_port (char * mode_str);
373SCM_API SCM scm_sys_make_void_port (SCM mode);
d617ee18 374
a535e9f5
AW
375/* Initialization. */
376SCM_INTERNAL void scm_init_ports (void);
d617ee18
MV
377
378
fca14149
AW
379/* Inline function implementations. */
380
381#if SCM_CAN_INLINE || defined SCM_INLINE_C_IMPLEMENTING_INLINES
382SCM_INLINE_IMPLEMENTATION int
92c0ebac 383scm_c_lock_port (SCM port, scm_i_pthread_mutex_t **lock)
fca14149 384{
92c0ebac 385 *lock = SCM_PTAB_ENTRY (port)->lock;
fca14149 386
92c0ebac
AW
387 if (*lock)
388 return scm_i_pthread_mutex_lock (*lock);
389 else
390 return 0;
fca14149
AW
391}
392
393SCM_INLINE_IMPLEMENTATION int
92c0ebac 394scm_c_try_lock_port (SCM port, scm_i_pthread_mutex_t **lock)
fca14149 395{
92c0ebac
AW
396 *lock = SCM_PTAB_ENTRY (port)->lock;
397 if (*lock)
398 {
399 int ret = scm_i_pthread_mutex_trylock (*lock);
400 if (ret != 0)
401 *lock = NULL;
402 return ret;
403 }
404 else
405 return 0;
fca14149
AW
406}
407
408SCM_INLINE_IMPLEMENTATION int
0d959103 409scm_get_byte_or_eof_unlocked (SCM port)
fca14149
AW
410{
411 int c;
412 scm_t_port *pt = SCM_PTAB_ENTRY (port);
413
414 if (pt->rw_active == SCM_PORT_WRITE)
415 /* may be marginally faster than calling scm_flush. */
62bd5d66 416 SCM_PORT_DESCRIPTOR (port)->flush (port);
fca14149
AW
417
418 if (pt->rw_random)
419 pt->rw_active = SCM_PORT_READ;
420
421 if (pt->read_pos >= pt->read_end)
422 {
4251ae2e 423 if (SCM_UNLIKELY (scm_fill_input_unlocked (port) == EOF))
fca14149
AW
424 return EOF;
425 }
426
427 c = *(pt->read_pos++);
428
429 return c;
430}
431
432/* Like `scm_get_byte_or_eof' but does not change PORT's `read_pos'. */
433SCM_INLINE_IMPLEMENTATION int
0d959103 434scm_peek_byte_or_eof_unlocked (SCM port)
fca14149
AW
435{
436 int c;
437 scm_t_port *pt = SCM_PTAB_ENTRY (port);
438
439 if (pt->rw_active == SCM_PORT_WRITE)
440 /* may be marginally faster than calling scm_flush. */
62bd5d66 441 SCM_PORT_DESCRIPTOR (port)->flush (port);
fca14149
AW
442
443 if (pt->rw_random)
444 pt->rw_active = SCM_PORT_READ;
445
446 if (pt->read_pos >= pt->read_end)
447 {
4251ae2e 448 if (SCM_UNLIKELY (scm_fill_input_unlocked (port) == EOF))
fca14149
AW
449 return EOF;
450 }
451
452 c = *pt->read_pos;
453
454 return c;
455}
456
457SCM_INLINE_IMPLEMENTATION void
0607ebbf 458scm_putc_unlocked (char c, SCM port)
fca14149
AW
459{
460 SCM_ASSERT_TYPE (SCM_OPOUTPORTP (port), port, 0, NULL, "output port");
f209aeee 461 scm_lfwrite_unlocked (&c, 1, port);
fca14149
AW
462}
463
464SCM_INLINE_IMPLEMENTATION void
0607ebbf 465scm_puts_unlocked (const char *s, SCM port)
fca14149
AW
466{
467 SCM_ASSERT_TYPE (SCM_OPOUTPORTP (port), port, 0, NULL, "output port");
f209aeee 468 scm_lfwrite_unlocked (s, strlen (s), port);
fca14149
AW
469}
470#endif /* SCM_CAN_INLINE || defined SCM_INLINE_C_IMPLEMENTING_INLINES */
471
22a52da1 472#endif /* SCM_PORTS_H */
89e00824
ML
473
474/*
475 Local Variables:
476 c-file-style: "gnu"
477 End:
478*/