#include <config.h>
#include "lisp.h"
-#include <limits.h>
#include "buffer.h"
#include "insdel.h"
/* Functions are as follows:
-Lstream *Lstream_new (Lstream_implementation *imp, CONST char *mode)
+Lstream *Lstream_new (Lstream_implementation *imp, const char *mode)
Allocate and return a new Lstream. This function is not
really meant to be called directly; rather, each stream type
should provide its own stream creation function, which
0 on success, -1 on error.
int Lstream_getc (Lstream *stream)
- Read one byte from the stream. This is a macro and so it
- is very efficient. The STREAM argument is evaluated more
- than once. Return value is -1 for EOF or error.
+ Read one byte from the stream and returns it as an unsigned
+ char cast to an int, or EOF on end of file or error.
+ This is a macro and so it is very efficient. The STREAM
+ argument is evaluated more than once.
void Lstream_ungetc (Lstream *stream, int c)
- Push one byte back onto the input queue. This will be the
- next byte read from the stream. Any number of bytes can be
- pushed back and will be read in the reverse order they were
- pushed back -- most recent first. (This is necessary for
- consistency -- if there are a number of bytes that have been
- unread and I read and unread a byte, it needs to be the first
- to be read again.) This is a macro and so it is very
- efficient. The C argument is only evaluated once but the
- STREAM argument is evaluated more than once.
+ Push one byte back onto the input queue, cast to unsigned char.
+ This will be the next byte read from the stream. Any number
+ of bytes can be pushed back and will be read in the reverse
+ order they were pushed back -- most recent first. (This is
+ necessary for consistency -- if there are a number of bytes
+ that have been unread and I read and unread a byte, it needs
+ to be the first to be read again.) This is a macro and so it
+ is very efficient. The C argument is only evaluated once but
+ the STREAM argument is evaluated more than once.
int Lstream_fputc (Lstream *stream, int c)
int Lstream_fgetc (Lstream *stream)
void Lstream_fungetc (Lstream *stream, int c)
Function equivalents of the above macros.
-int Lstream_read (Lstream *stream, void *data, size_t size)
+ssize_t Lstream_read (Lstream *stream, void *data, size_t size)
Read SIZE bytes of DATA from the stream. Return the number of
bytes read. 0 means EOF. -1 means an error occurred and no
bytes were read.
-int Lstream_write (Lstream *stream, void *data, size_t size)
+ssize_t Lstream_write (Lstream *stream, void *data, size_t size)
Write SIZE bytes of DATA to the stream. Return the number of
bytes written. -1 means an error occurred and no bytes were
written.
#define MAX_READ_SIZE 512
static Lisp_Object
-mark_lstream (Lisp_Object obj, void (*markobj) (Lisp_Object))
+mark_lstream (Lisp_Object obj)
{
Lstream *lstr = XLSTREAM (obj);
- return lstr->imp->marker ? (lstr->imp->marker) (obj, markobj) : Qnil;
+ return lstr->imp->marker ? (lstr->imp->marker) (obj) : Qnil;
}
static void
}
static size_t
-sizeof_lstream (CONST void *header)
+sizeof_lstream (const void *header)
{
- CONST Lstream *lstr = (CONST Lstream *) header;
+ const Lstream *lstr = (const Lstream *) header;
return sizeof (*lstr) + lstr->imp->size - 1;
}
DEFINE_LRECORD_SEQUENCE_IMPLEMENTATION ("stream", lstream,
mark_lstream, print_lstream,
- finalize_lstream, 0, 0,
+ finalize_lstream, 0, 0, 0,
sizeof_lstream, Lstream);
\f
void
}
}
-static CONST Lstream_implementation *lstream_types[32];
+static const Lstream_implementation *lstream_types[32];
static Lisp_Object Vlstream_free_list[32];
static int lstream_type_count;
Lstream *
-Lstream_new (CONST Lstream_implementation *imp, CONST char *mode)
+Lstream_new (const Lstream_implementation *imp, const char *mode)
{
Lstream *p;
int i;
#define Lstream_internal_error(reason, lstr) \
Lstream_signal_simple_error ("Internal error: " reason, lstr)
-static void Lstream_signal_simple_error (CONST char *reason, Lstream *lstr)
+static void Lstream_signal_simple_error (const char *reason, Lstream *lstr)
{
Lisp_Object obj;
XSETLSTREAM (obj, lstr);
int
Lstream_flush_out (Lstream *lstr)
{
- int num_written;
+ ssize_t num_written;
while (lstr->out_buffer_ind > 0)
{
- int size = lstr->out_buffer_ind;
+ size_t size = lstr->out_buffer_ind;
if (! (lstr->flags & LSTREAM_FL_IS_OPEN))
Lstream_internal_error ("lstream not open", lstr);
if (! (lstr->flags & LSTREAM_FL_WRITE))
character at the end. We need to spit back that
incomplete character. */
{
- CONST unsigned char *data = lstr->out_buffer;
- CONST unsigned char *dataend = data + size - 1;
+ const unsigned char *data = lstr->out_buffer;
+ const unsigned char *dataend = data + size - 1;
assert (size > 0); /* safety check ... */
/* Optimize the most common case. */
if (!BYTE_ASCII_P (*dataend))
the attempt to write the data might have resulted in an
EWOULDBLOCK error. */
return 0;
- else if (num_written >= (int) lstr->out_buffer_ind)
+ else if (num_written >= lstr->out_buffer_ind)
lstr->out_buffer_ind = 0;
else if (num_written > 0)
{
if it's getting EWOULDBLOCK errors. We have to keep stocking them
up until they can be written, so as to avoid losing data. */
-static int
+static size_t
Lstream_adding (Lstream *lstr, size_t num, int force)
{
- /* Compute the size that the outbuffer needs to be after the
- chars are added. */
- size_t size_needed = max (lstr->out_buffer_size,
- num + lstr->out_buffer_ind);
+ size_t size = num + lstr->out_buffer_ind;
+
+ if (size <= lstr->out_buffer_size)
+ return num;
+
/* Maybe chop it down so that we don't buffer more characters
than our advertised buffering size. */
- if (!force)
- size_needed = min (lstr->buffering_size, size_needed);
- DO_REALLOC (lstr->out_buffer, lstr->out_buffer_size,
- size_needed, unsigned char);
- /* There might be more data buffered than the buffering size,
- so make sure we don't return a negative number here. */
- return max (0, min (num, size_needed - lstr->out_buffer_ind));
+ if ((size > lstr->buffering_size) && !force)
+ {
+ size = lstr->buffering_size;
+ /* There might be more data buffered than the buffering size. */
+ if (size <= lstr->out_buffer_ind)
+ return 0;
+ }
+
+ DO_REALLOC (lstr->out_buffer, lstr->out_buffer_size, size, unsigned char);
+
+ return size - lstr->out_buffer_ind;
}
/* Like Lstream_write(), but does not handle line-buffering correctly. */
-static int
-Lstream_write_1 (Lstream *lstr, CONST void *data, size_t size)
+static ssize_t
+Lstream_write_1 (Lstream *lstr, const void *data, size_t size)
{
- CONST unsigned char *p = (CONST unsigned char *) data;
- int off = 0;
+ const unsigned char *p = (const unsigned char *) data;
+ ssize_t off = 0;
if (! (lstr->flags & LSTREAM_FL_IS_OPEN))
Lstream_internal_error ("lstream not open", lstr);
if (! (lstr->flags & LSTREAM_FL_WRITE))
while (1)
{
/* Figure out how much we can add to the buffer */
- int chunk = Lstream_adding (lstr, size, 0);
+ size_t chunk = Lstream_adding (lstr, size, 0);
if (chunk == 0)
{
if (couldnt_write_last_time)
/* If the stream is not line-buffered, then we can just call
Lstream_write_1(), which writes in chunks. Otherwise, we
repeatedly call Lstream_putc(), which knows how to handle
- line buffering. */
+ line buffering. Returns number of bytes written. */
-int
-Lstream_write (Lstream *lstr, CONST void *data, size_t size)
+ssize_t
+Lstream_write (Lstream *lstr, const void *data, size_t size)
{
- int i;
- CONST unsigned char *p = (CONST unsigned char *) data;
+ size_t i;
+ const unsigned char *p = (const unsigned char *) data;
if (size == 0)
return size;
if (lstr->buffering != LSTREAM_LINE_BUFFERED)
return Lstream_write_1 (lstr, data, size);
- for (i = 0; i < (int) size; i++)
+ for (i = 0; i < size; i++)
{
if (Lstream_putc (lstr, p[i]) < 0)
break;
}
- return i == 0 ? -1 : 0;
+ return i == 0 ? -1 : (ssize_t) i;
}
int
Lstream_was_blocked_p (Lstream *lstr)
{
- if (lstr->imp->was_blocked_p)
- return (lstr->imp->was_blocked_p) (lstr);
- else
- return 0;
+ return lstr->imp->was_blocked_p ? lstr->imp->was_blocked_p (lstr) : 0;
}
-static int
+static ssize_t
Lstream_raw_read (Lstream *lstr, unsigned char *buffer, size_t size)
{
if (! (lstr->flags & LSTREAM_FL_IS_OPEN))
/* Assuming the buffer is empty, fill it up again. */
-static int
+static ssize_t
Lstream_read_more (Lstream *lstr)
{
#if 0
- int size_needed = max (1, min (MAX_READ_SIZE, lstr->buffering_size));
+ ssize_t size_needed = max (1, min (MAX_READ_SIZE, lstr->buffering_size));
#else
/* If someone requested a larger buffer size, so be it! */
- int size_needed = max (1, lstr->buffering_size);
+ ssize_t size_needed = max (1, lstr->buffering_size);
#endif
- int size_gotten;
+ ssize_t size_gotten;
DO_REALLOC (lstr->in_buffer, lstr->in_buffer_size,
size_needed, unsigned char);
return size_gotten < 0 ? -1 : size_gotten;
}
-int
+ssize_t
Lstream_read (Lstream *lstr, void *data, size_t size)
{
unsigned char *p = (unsigned char *) data;
- int off = 0;
+ size_t off = 0;
size_t chunk;
int error_occurred = 0;
if (chunk > 0)
{
/* The bytes come back in reverse order. */
- for (; off < (int) chunk; off++)
+ for (; off < chunk; off++)
p[off] = lstr->unget_buffer[--lstr->unget_buffer_ind];
lstr->byte_count += chunk;
size -= chunk;
/* If we need some more, try to get some more from the stream's end */
if (size > 0)
{
- int retval = Lstream_read_more (lstr);
+ ssize_t retval = Lstream_read_more (lstr);
if (retval < 0)
error_occurred = 1;
if (retval <= 0)
/* It's quite possible for us to get passed an incomplete
character at the end. We need to spit back that
incomplete character. */
- CONST unsigned char *dataend = p + off - 1;
+ const unsigned char *dataend = p + off - 1;
/* Optimize the most common case. */
if (!BYTE_ASCII_P (*dataend))
{
VALIDATE_CHARPTR_BACKWARD (dataend);
if (dataend + REP_BYTES_BY_FIRST_BYTE (*dataend) != p + off)
{
- int newoff = dataend - p;
+ size_t newoff = dataend - p;
/* If not, chop the size down to ignore the last char
and stash it away for next time. */
Lstream_unread (lstr, dataend, off - newoff);
}
}
- return ((off == 0 && error_occurred) ? -1 : off);
+ return off == 0 && error_occurred ? -1 : (ssize_t) off;
}
void
-Lstream_unread (Lstream *lstr, CONST void *data, size_t size)
+Lstream_unread (Lstream *lstr, const void *data, size_t size)
{
- int i;
- unsigned char *p = (unsigned char *) data;
+ const unsigned char *p = (const unsigned char *) data;
/* Make sure buffer is big enough */
-
DO_REALLOC (lstr->unget_buffer, lstr->unget_buffer_size,
lstr->unget_buffer_ind + size, unsigned char);
+ lstr->byte_count -= size;
+
/* Bytes have to go on in reverse order -- they are reversed
again when read back. */
- for (i = size - 1; i >= 0; i--)
- lstr->unget_buffer[lstr->unget_buffer_ind++] = p[i];
- lstr->byte_count -= size;
+ while (size--)
+ lstr->unget_buffer[lstr->unget_buffer_ind++] = p[size];
}
int
static int
Lstream_pseudo_close (Lstream *lstr)
{
- int rc;
-
if (!lstr->flags & LSTREAM_FL_IS_OPEN)
Lstream_internal_error ("lstream is not open", lstr);
/* don't check errors here -- best not to risk file descriptor loss */
- rc = Lstream_flush (lstr);
-
- return rc;
+ return Lstream_flush (lstr);
}
int
Lstream_fputc (Lstream *lstr, int c)
{
unsigned char ch = (unsigned char) c;
- int retval = Lstream_write_1 (lstr, &ch, 1);
+ ssize_t retval = Lstream_write_1 (lstr, &ch, 1);
if (retval >= 0 && lstr->buffering == LSTREAM_LINE_BUFFERED && ch == '\n')
return Lstream_flush_out (lstr);
return retval < 0 ? -1 : 0;
sizeof (struct stdio_stream));
static Lisp_Object
-make_stdio_stream_1 (FILE *stream, int flags, CONST char *mode)
+make_stdio_stream_1 (FILE *stream, int flags, const char *mode)
{
Lisp_Object obj;
Lstream *lstr = Lstream_new (lstream_stdio, mode);
return make_stdio_stream_1 (stream, flags, "w");
}
-static int
+/* #### From reading the Unix 98 specification, it appears that if we
+ want stdio_reader() to be completely correct, we should check for
+ 0 < val < size and if so, check to see if an error has occurred.
+ If an error has occurred, but val is non-zero, we should go ahead
+ and act as if the read was successful, but remember in some fashion
+ or other, that an error has occurred, and report that on the next
+ call to stdio_reader instead of calling fread() again.
+
+ Currently, in such a case, we end up calling fread() twice and we
+ assume that
+
+ 1) this is not harmful, and
+ 2) the error will still be reported on the second read.
+
+ This is probably reasonable, so I don't think we should change this
+ code (it could even be argued that the error might have fixed
+ itself, so we should do the fread() again. */
+
+static ssize_t
stdio_reader (Lstream *stream, unsigned char *data, size_t size)
{
struct stdio_stream *str = STDIO_STREAM_DATA (stream);
- size_t val = fread (data, 1, (size_t) size, str->file);
+ size_t val = fread (data, 1, size, str->file);
if (!val && ferror (str->file))
return -1;
- return (int) val;
+ return val;
}
-static int
-stdio_writer (Lstream *stream, CONST unsigned char *data, size_t size)
+static ssize_t
+stdio_writer (Lstream *stream, const unsigned char *data, size_t size)
{
struct stdio_stream *str = STDIO_STREAM_DATA (stream);
size_t val = fwrite (data, 1, size, str->file);
if (!val && ferror (str->file))
return -1;
- return (int) val;
+ return val;
}
static int
if (stream->flags & LSTREAM_FL_WRITE)
return fflush (str->file);
else
- /* call fpurge? Only exists on some systems. #### Why not add a
- configure check for HAVE_FPURGE and utilize it on systems that
- support it? --hniksic */
return 0;
}
if (stream->flags & LSTREAM_FL_WRITE)
return fflush (str->file);
else
- /* call fpurge? Only exists on some systems. */
return 0;
}
ignored when writing); -1 for unlimited. */
static Lisp_Object
make_filedesc_stream_1 (int filedesc, int offset, int count, int flags,
- CONST char *mode)
+ const char *mode)
{
Lisp_Object obj;
Lstream *lstr = Lstream_new (lstream_filedesc, mode);
return make_filedesc_stream_1 (filedesc, offset, count, flags, "w");
}
-static int
+static ssize_t
filedesc_reader (Lstream *stream, unsigned char *data, size_t size)
{
- int nread;
+ ssize_t nread;
struct filedesc_stream *str = FILEDESC_STREAM_DATA (stream);
if (str->end_pos >= 0)
size = min (size, (size_t) (str->end_pos - str->current_pos));
- nread = (str->allow_quit ? read_allowing_quit : read) (str->fd, data, size);
+ nread = str->allow_quit ?
+ read_allowing_quit (str->fd, data, size) :
+ read (str->fd, data, size);
if (nread > 0)
str->current_pos += nread;
return nread;
return 0;
}
-static int
-filedesc_writer (Lstream *stream, CONST unsigned char *data, size_t size)
+static ssize_t
+filedesc_writer (Lstream *stream, const unsigned char *data, size_t size)
{
struct filedesc_stream *str = FILEDESC_STREAM_DATA (stream);
- int retval;
+ ssize_t retval;
int need_newline = 0;
/* This function would be simple if it were not for the blasted
if (str->pty_flushing)
{
/* To make life easy, only send out one line at the most. */
- CONST unsigned char *ptr;
+ const unsigned char *ptr;
- ptr = (CONST unsigned char *) memchr (data, '\n', size);
+ ptr = (const unsigned char *) memchr (data, '\n', size);
if (ptr)
need_newline = 1;
else
/**** start of non-PTY-crap ****/
if (size > 0)
- retval = ((str->allow_quit ? write_allowing_quit : write)
- (str->fd, data, size));
+ retval = str->allow_quit ?
+ write_allowing_quit (str->fd, data, size) :
+ write (str->fd, data, size);
else
retval = 0;
if (retval < 0 && errno_would_block_p (errno) && str->blocked_ok)
out for EWOULDBLOCK. */
if (str->chars_sans_newline >= str->pty_max_bytes)
{
- int retval2 = ((str->allow_quit ? write_allowing_quit : write)
- (str->fd, &str->eof_char, 1));
+ ssize_t retval2 = str->allow_quit ?
+ write_allowing_quit (str->fd, &str->eof_char, 1) :
+ write (str->fd, &str->eof_char, 1);
+
if (retval2 > 0)
str->chars_sans_newline = 0;
else if (retval2 < 0)
if (need_newline)
{
Bufbyte nl = '\n';
- int retval2 = ((str->allow_quit ? write_allowing_quit : write)
- (str->fd, &nl, 1));
+ ssize_t retval2 = str->allow_quit ?
+ write_allowing_quit (str->fd, &nl, 1) :
+ write (str->fd, &nl, 1);
+
if (retval2 > 0)
{
str->chars_sans_newline = 0;
return obj;
}
-static int
+static ssize_t
lisp_string_reader (Lstream *stream, unsigned char *data, size_t size)
{
struct lisp_string_stream *str = LISP_STRING_STREAM_DATA (stream);
}
static Lisp_Object
-lisp_string_marker (Lisp_Object stream, void (*markobj) (Lisp_Object))
+lisp_string_marker (Lisp_Object stream)
{
struct lisp_string_stream *str = LISP_STRING_STREAM_DATA (XLSTREAM (stream));
return str->obj;
struct fixed_buffer_stream
{
- CONST unsigned char *inbuf;
+ const unsigned char *inbuf;
unsigned char *outbuf;
size_t size;
size_t offset;
sizeof (struct fixed_buffer_stream));
Lisp_Object
-make_fixed_buffer_input_stream (CONST unsigned char *buf, size_t size)
+make_fixed_buffer_input_stream (const void *buf, size_t size)
{
Lisp_Object obj;
Lstream *lstr = Lstream_new (lstream_fixed_buffer, "r");
struct fixed_buffer_stream *str = FIXED_BUFFER_STREAM_DATA (lstr);
- str->inbuf = buf;
+ str->inbuf = (const unsigned char *) buf;
str->size = size;
XSETLSTREAM (obj, lstr);
return obj;
}
Lisp_Object
-make_fixed_buffer_output_stream (unsigned char *buf, size_t size)
+make_fixed_buffer_output_stream (void *buf, size_t size)
{
Lisp_Object obj;
Lstream *lstr = Lstream_new (lstream_fixed_buffer, "w");
struct fixed_buffer_stream *str = FIXED_BUFFER_STREAM_DATA (lstr);
- str->outbuf = buf;
+ str->outbuf = (unsigned char *) buf;
str->size = size;
XSETLSTREAM (obj, lstr);
return obj;
}
-static int
+static ssize_t
fixed_buffer_reader (Lstream *stream, unsigned char *data, size_t size)
{
struct fixed_buffer_stream *str = FIXED_BUFFER_STREAM_DATA (stream);
return size;
}
-static int
-fixed_buffer_writer (Lstream *stream, CONST unsigned char *data, size_t size)
+static ssize_t
+fixed_buffer_writer (Lstream *stream, const unsigned char *data, size_t size)
{
struct fixed_buffer_stream *str = FIXED_BUFFER_STREAM_DATA (stream);
if (str->offset == str->size)
return 0;
}
-CONST unsigned char *
+const unsigned char *
fixed_buffer_input_stream_ptr (Lstream *stream)
{
assert (stream->imp == lstream_fixed_buffer);
return obj;
}
-static int
-resizing_buffer_writer (Lstream *stream, CONST unsigned char *data, size_t size)
+static ssize_t
+resizing_buffer_writer (Lstream *stream, const unsigned char *data, size_t size)
{
struct resizing_buffer_stream *str = RESIZING_BUFFER_STREAM_DATA (stream);
DO_REALLOC (str->buf, str->allocked, str->stored + size, unsigned char);
return obj;
}
-static int
-dynarr_writer (Lstream *stream, CONST unsigned char *data, size_t size)
+static ssize_t
+dynarr_writer (Lstream *stream, const unsigned char *data, size_t size)
{
struct dynarr_stream *str = DYNARR_STREAM_DATA (stream);
Dynarr_add_many (str->dyn, data, size);
static Lisp_Object
make_lisp_buffer_stream_1 (struct buffer *buf, Bufpos start, Bufpos end,
- int flags, CONST char *mode)
+ int flags, const char *mode)
{
Lisp_Object obj;
Lstream *lstr;
return lstr;
}
-static int
+static ssize_t
lisp_buffer_reader (Lstream *stream, unsigned char *data, size_t size)
{
struct lisp_buffer_stream *str = LISP_BUFFER_STREAM_DATA (stream);
return data - orig_data;
}
-static int
-lisp_buffer_writer (Lstream *stream, CONST unsigned char *data, size_t size)
+static ssize_t
+lisp_buffer_writer (Lstream *stream, const unsigned char *data, size_t size)
{
struct lisp_buffer_stream *str = LISP_BUFFER_STREAM_DATA (stream);
Bufpos pos;
}
static Lisp_Object
-lisp_buffer_marker (Lisp_Object stream, void (*markobj) (Lisp_Object))
+lisp_buffer_marker (Lisp_Object stream)
{
struct lisp_buffer_stream *str =
LISP_BUFFER_STREAM_DATA (XLSTREAM (stream));
- markobj (str->start);
- markobj (str->end);
+ mark_object (str->start);
+ mark_object (str->end);
return str->buffer;
}
}
void
-vars_of_lstream (void)
+reinit_vars_of_lstream (void)
{
int i;
for (i = 0; i < countof (Vlstream_free_list); i++)
{
Vlstream_free_list[i] = Qnil;
- staticpro (&Vlstream_free_list[i]);
+ staticpro_nodump (&Vlstream_free_list[i]);
}
}
+
+void
+vars_of_lstream (void)
+{
+ INIT_LRECORD_IMPLEMENTATION (lstream);
+
+ reinit_vars_of_lstream ();
+}