import -ko -b 1.1.3 XEmacs XEmacs-21_2 r21-2-35
[chise/xemacs-chise.git.1] / src / lstream.c
1 /* Generic stream implementation.
2    Copyright (C) 1995 Free Software Foundation, Inc.
3    Copyright (C) 1995 Sun Microsystems, Inc.
4    Copyright (C) 1996 Ben Wing.
5
6 This file is part of XEmacs.
7
8 XEmacs is free software; you can redistribute it and/or modify it
9 under the terms of the GNU General Public License as published by the
10 Free Software Foundation; either version 2, or (at your option) any
11 later version.
12
13 XEmacs is distributed in the hope that it will be useful, but WITHOUT
14 ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
15 FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
16 for more details.
17
18 You should have received a copy of the GNU General Public License
19 along with XEmacs; see the file COPYING.  If not, write to
20 the Free Software Foundation, Inc., 59 Temple Place - Suite 330,
21 Boston, MA 02111-1307, USA.  */
22
23 /* Synched up with: Not in FSF. */
24
25 /* Written by Ben Wing. */
26
27 #include <config.h>
28 #include "lisp.h"
29
30 #include "buffer.h"
31 #include "insdel.h"
32 #include "lstream.h"
33
34 #include "sysfile.h"
35 #include <errno.h>
36
37 /* This function provides a generic buffering stream implementation.
38    Conceptually, you send data to the stream or read data from the
39    stream, not caring what's on the other end of the stream.  The
40    other end could be another stream, a file descriptor, a stdio
41    stream, a fixed block of memory, a reallocating block of memory,
42    etc.  The main purpose of the stream is to provide a standard
43    interface and to do buffering.  Macros are defined to read
44    or write characters, so the calling functions do not have to
45    worry about blocking data together in order to achieve efficiency.
46    */
47
48 /* Note that this object is called "stream" in Lisp but "lstream"
49    in C.  The reason for this is that "stream" is too generic a name
50    for C; too much likelihood of conflict/confusion with C++, etc. */
51
52 /* Functions are as follows:
53
54 Lstream *Lstream_new (Lstream_implementation *imp, const char *mode)
55         Allocate and return a new Lstream.  This function is not
56         really meant to be called directly; rather, each stream type
57         should provide its own stream creation function, which
58         creates the stream and does any other necessary creation
59         stuff (e.g. opening a file).
60
61 void Lstream_set_buffering (Lstream *lstr, Lstream_buffering buffering,
62                             int buffering_size)
63         Change the buffering of a stream.  See lstream.h.  By default
64         the buffering is STREAM_BLOCK_BUFFERED.
65
66 int Lstream_flush (Lstream *lstr)
67         Flush out any pending unwritten data in the stream.  Clear
68         any buffered input data.  Returns 0 on success, -1 on error.
69
70 int Lstream_putc (Lstream *stream, int c)
71         Write out one byte to the stream.  This is a macro and so
72         it is very efficient.  The C argument is only evaluated once
73         but the STREAM argument is evaluated more than once.  Returns
74         0 on success, -1 on error.
75
76 int Lstream_getc (Lstream *stream)
77         Read one byte from the stream.  This is a macro and so it
78         is very efficient.  The STREAM argument is evaluated more
79         than once.  Return value is -1 for EOF or error.
80
81 void Lstream_ungetc (Lstream *stream, int c)
82         Push one byte back onto the input queue.  This will be the
83         next byte read from the stream.  Any number of bytes can be
84         pushed back and will be read in the reverse order they were
85         pushed back -- most recent first. (This is necessary for
86         consistency -- if there are a number of bytes that have been
87         unread and I read and unread a byte, it needs to be the first
88         to be read again.) This is a macro and so it is very
89         efficient.  The C argument is only evaluated once but the
90         STREAM argument is evaluated more than once.
91
92 int Lstream_fputc (Lstream *stream, int c)
93 int Lstream_fgetc (Lstream *stream)
94 void Lstream_fungetc (Lstream *stream, int c)
95         Function equivalents of the above macros.
96
97 ssize_t Lstream_read (Lstream *stream, void *data, size_t size)
98         Read SIZE bytes of DATA from the stream.  Return the number of
99         bytes read.  0 means EOF. -1 means an error occurred and no
100         bytes were read.
101
102 ssize_t Lstream_write (Lstream *stream, void *data, size_t size)
103         Write SIZE bytes of DATA to the stream.  Return the number of
104         bytes written.  -1 means an error occurred and no bytes were
105         written.
106
107 void Lstream_unread (Lstream *stream, void *data, size_t size)
108         Push back SIZE bytes of DATA onto the input queue.  The
109         next call to Lstream_read() with the same size will read the
110         same bytes back.  Note that this will be the case even if
111         there is other pending unread data.
112
113 int Lstream_delete (Lstream *stream)
114         Frees all memory associated with the stream is freed.  Calling
115         this is not strictly necessary, but it is much more efficient
116         than having the Lstream be garbage-collected.
117
118 int Lstream_close (Lstream *stream)
119         Close the stream.  All data will be flushed out.
120
121 void Lstream_reopen (Lstream *stream)
122         Reopen a closed stream.  This enables I/O on it again.
123         This is not meant to be called except from a wrapper routine
124         that reinitializes variables and such -- the close routine
125         may well have freed some necessary storage structures, for
126         example.
127
128 void Lstream_rewind (Lstream *stream)
129         Rewind the stream to the beginning.
130 */
131
132 #define DEFAULT_BLOCK_BUFFERING_SIZE 512
133 #define MAX_READ_SIZE 512
134
135 static Lisp_Object
136 mark_lstream (Lisp_Object obj)
137 {
138   Lstream *lstr = XLSTREAM (obj);
139   return lstr->imp->marker ? (lstr->imp->marker) (obj) : Qnil;
140 }
141
142 static void
143 print_lstream (Lisp_Object obj, Lisp_Object printcharfun, int escapeflag)
144 {
145   Lstream *lstr = XLSTREAM (obj);
146   char buf[200];
147
148   sprintf (buf, "#<INTERNAL OBJECT (XEmacs bug?) (%s lstream) 0x%lx>",
149            lstr->imp->name, (long) lstr);
150   write_c_string (buf, printcharfun);
151 }
152
153 static void
154 finalize_lstream (void *header, int for_disksave)
155 {
156   /* WARNING WARNING WARNING.  This function (and all finalize functions)
157      may get called more than once on the same object, and may get called
158      (at dump time) on objects that are not being released. */
159   Lstream *lstr = (Lstream *) header;
160
161 #if 0 /* this may cause weird Broken Pipes? */
162   if (for_disksave)
163     {
164       Lstream_pseudo_close (lstr);
165       return;
166     }
167 #endif
168   if (lstr->flags & LSTREAM_FL_IS_OPEN)
169     {
170       if (for_disksave)
171         {
172           if (lstr->flags & LSTREAM_FL_CLOSE_AT_DISKSAVE)
173             Lstream_close (lstr);
174         }
175       else
176         /* Just close. */
177         Lstream_close (lstr);
178     }
179 }
180
181 static size_t
182 sizeof_lstream (const void *header)
183 {
184   const Lstream *lstr = (const Lstream *) header;
185   return sizeof (*lstr) + lstr->imp->size - 1;
186 }
187
188 DEFINE_LRECORD_SEQUENCE_IMPLEMENTATION ("stream", lstream,
189                                         mark_lstream, print_lstream,
190                                         finalize_lstream, 0, 0, 0,
191                                         sizeof_lstream, Lstream);
192 \f
193 void
194 Lstream_set_buffering (Lstream *lstr, Lstream_buffering buffering,
195                        int buffering_size)
196 {
197   lstr->buffering = buffering;
198   switch (buffering)
199     {
200     case LSTREAM_UNBUFFERED:
201       lstr->buffering_size = 0; break;
202     case LSTREAM_BLOCK_BUFFERED:
203       lstr->buffering_size = DEFAULT_BLOCK_BUFFERING_SIZE; break;
204     case LSTREAM_BLOCKN_BUFFERED:
205       lstr->buffering_size = buffering_size; break;
206     case LSTREAM_LINE_BUFFERED:
207     case LSTREAM_UNLIMITED:
208       lstr->buffering_size = INT_MAX; break;
209     }
210 }
211
212 static const Lstream_implementation *lstream_types[32];
213 static Lisp_Object Vlstream_free_list[32];
214 static int lstream_type_count;
215
216 Lstream *
217 Lstream_new (const Lstream_implementation *imp, const char *mode)
218 {
219   Lstream *p;
220   int i;
221
222   for (i = 0; i < lstream_type_count; i++)
223     {
224       if (lstream_types[i] == imp)
225         break;
226     }
227
228   if (i == lstream_type_count)
229     {
230       assert (lstream_type_count < countof (lstream_types));
231       lstream_types[lstream_type_count] = imp;
232       Vlstream_free_list[lstream_type_count] =
233         make_lcrecord_list (sizeof (*p) + imp->size - 1,
234                             &lrecord_lstream);
235       lstream_type_count++;
236     }
237
238   p = XLSTREAM (allocate_managed_lcrecord (Vlstream_free_list[i]));
239   /* Zero it out, except the header. */
240   memset ((char *) p + sizeof (p->header), 0,
241           sizeof (*p) - sizeof (p->header) + imp->size - 1);
242   p->imp = imp;
243   Lstream_set_buffering (p, LSTREAM_BLOCK_BUFFERED, 0);
244   p->flags = LSTREAM_FL_IS_OPEN;
245
246   /* convert mode (one of "r", "w", "rc", "wc") to p->flags */
247   assert (mode[0] == 'r' || mode[0] == 'w');
248   assert (mode[1] == 'c' || mode[1] == '\0');
249   p->flags |= (mode[0] == 'r' ? LSTREAM_FL_READ : LSTREAM_FL_WRITE);
250   if (mode[1] == 'c')
251     p->flags |= LSTREAM_FL_NO_PARTIAL_CHARS;
252
253   return p;
254 }
255
256 void
257 Lstream_set_character_mode (Lstream *lstr)
258 {
259   lstr->flags |= LSTREAM_FL_NO_PARTIAL_CHARS;
260 }
261
262 void
263 Lstream_delete (Lstream *lstr)
264 {
265   int i;
266   Lisp_Object val;
267
268   XSETLSTREAM (val, lstr);
269   for (i = 0; i < lstream_type_count; i++)
270     {
271       if (lstream_types[i] == lstr->imp)
272         {
273           free_managed_lcrecord (Vlstream_free_list[i], val);
274           return;
275         }
276     }
277
278   abort ();
279 }
280
281 #define Lstream_internal_error(reason, lstr) \
282   Lstream_signal_simple_error ("Internal error: " reason, lstr)
283
284 static void Lstream_signal_simple_error (const char *reason, Lstream *lstr)
285 {
286   Lisp_Object obj;
287   XSETLSTREAM (obj, lstr);
288   signal_simple_error (reason, obj);
289 }
290
291 void
292 Lstream_reopen (Lstream *lstr)
293 {
294   if (lstr->flags & LSTREAM_FL_IS_OPEN)
295     Lstream_internal_error ("lstream already open", lstr);
296   lstr->flags |= LSTREAM_FL_IS_OPEN;
297 }
298
299 /* Attempt to flush out all of the buffered data for writing. */
300
301 int
302 Lstream_flush_out (Lstream *lstr)
303 {
304   ssize_t num_written;
305
306   while (lstr->out_buffer_ind > 0)
307     {
308       size_t size = lstr->out_buffer_ind;
309       if (! (lstr->flags & LSTREAM_FL_IS_OPEN))
310         Lstream_internal_error ("lstream not open", lstr);
311       if (! (lstr->flags & LSTREAM_FL_WRITE))
312         Lstream_internal_error ("lstream not open for writing", lstr);
313       if (!lstr->imp->writer)
314         Lstream_internal_error ("lstream has no writer", lstr);
315
316       if (lstr->flags & LSTREAM_FL_NO_PARTIAL_CHARS)
317         /* It's quite possible for us to get passed an incomplete
318            character at the end.  We need to spit back that
319            incomplete character. */
320         {
321           const unsigned char *data = lstr->out_buffer;
322           const unsigned char *dataend = data + size - 1;
323           assert (size > 0); /* safety check ... */
324           /* Optimize the most common case. */
325           if (!BYTE_ASCII_P (*dataend))
326             {
327               /* Go back to the beginning of the last (and possibly partial)
328                  character, and bump forward to see if the character is
329                  complete. */
330               VALIDATE_CHARPTR_BACKWARD (dataend);
331               if (dataend + REP_BYTES_BY_FIRST_BYTE (*dataend) != data + size)
332                 /* If not, chop the size down to ignore the last char
333                    and stash it away for next time. */
334                 size = dataend - data;
335               /* If we don't even have one character to write, then just
336                  skip out. */
337               if (size == 0)
338                 break;
339             }
340         }
341
342       num_written = (lstr->imp->writer) (lstr, lstr->out_buffer, size);
343       if (num_written == 0)
344         /* If nothing got written, then just hold the data.  This may
345            occur, for example, if this stream does non-blocking I/O;
346            the attempt to write the data might have resulted in an
347            EWOULDBLOCK error. */
348         return 0;
349       else if (num_written >= lstr->out_buffer_ind)
350         lstr->out_buffer_ind = 0;
351       else if (num_written > 0)
352         {
353           memmove (lstr->out_buffer, lstr->out_buffer + num_written,
354                    lstr->out_buffer_ind - num_written);
355           lstr->out_buffer_ind -= num_written;
356         }
357       else
358         /* If error, just hold the data, for similar reasons as above. */
359         return -1;
360     }
361
362   if (lstr->imp->flusher)
363     return (lstr->imp->flusher) (lstr);
364
365   return 0;
366 }
367
368 int
369 Lstream_flush (Lstream *lstr)
370 {
371   if (Lstream_flush_out (lstr) < 0)
372     return -1;
373
374   /* clear out buffered data */
375   lstr->in_buffer_current = lstr->in_buffer_ind = 0;
376   lstr->unget_buffer_ind = 0;
377
378   return 0;
379 }
380
381 /* We want to add NUM characters.  This function ensures that the
382    buffer is large enough for this (per the buffering size specified
383    in the stream) and returns the number of characters we can
384    actually write.  If FORCE is set, ignore the buffering size
385    and go ahead and make space for all the chars even if it exceeds
386    the buffering size. (This is used to deal with the possibility
387    that the stream writer might refuse to write any bytes now, e.g.
388    if it's getting EWOULDBLOCK errors.   We have to keep stocking them
389    up until they can be written, so as to avoid losing data. */
390
391 static size_t
392 Lstream_adding (Lstream *lstr, size_t num, int force)
393 {
394   size_t size = num + lstr->out_buffer_ind;
395
396   if (size <= lstr->out_buffer_size)
397     return num;
398
399   /* Maybe chop it down so that we don't buffer more characters
400      than our advertised buffering size. */
401   if ((size > lstr->buffering_size) && !force)
402     {
403       size = lstr->buffering_size;
404       /* There might be more data buffered than the buffering size. */
405       if (size <= lstr->out_buffer_ind)
406         return 0;
407     }
408
409   DO_REALLOC (lstr->out_buffer, lstr->out_buffer_size, size, unsigned char);
410
411   return size - lstr->out_buffer_ind;
412 }
413
414 /* Like Lstream_write(), but does not handle line-buffering correctly. */
415
416 static ssize_t
417 Lstream_write_1 (Lstream *lstr, const void *data, size_t size)
418 {
419   const unsigned char *p = (const unsigned char *) data;
420   ssize_t off = 0;
421   if (! (lstr->flags & LSTREAM_FL_IS_OPEN))
422     Lstream_internal_error ("lstream not open", lstr);
423   if (! (lstr->flags & LSTREAM_FL_WRITE))
424     Lstream_internal_error ("lstream not open for writing", lstr);
425   {
426     int couldnt_write_last_time = 0;
427
428     while (1)
429       {
430         /* Figure out how much we can add to the buffer */
431         size_t chunk = Lstream_adding (lstr, size, 0);
432         if (chunk == 0)
433           {
434             if (couldnt_write_last_time)
435               /* Ung, we ran out of space and tried to flush
436                  the buffer, but it didn't work because the stream
437                  writer is refusing to accept any data.  So we
438                  just have to squirrel away all the rest of the
439                  stuff. */
440               chunk = Lstream_adding (lstr, size, 1);
441             else
442               couldnt_write_last_time = 1;
443           }
444         /* Do it. */
445         if (chunk > 0)
446           {
447             memcpy (lstr->out_buffer + lstr->out_buffer_ind, p + off, chunk);
448             lstr->out_buffer_ind += chunk;
449             lstr->byte_count     += chunk;
450             size -= chunk;
451             off  += chunk;
452           }
453         /* If the buffer is full and we have more to add, flush it out. */
454         if (size > 0)
455           {
456             if (Lstream_flush_out (lstr) < 0)
457               {
458                 if (off == 0)
459                   return -1;
460                 else
461                   return off;
462               }
463           }
464         else
465           break;
466       }
467   }
468   return off;
469 }
470
471 /* If the stream is not line-buffered, then we can just call
472    Lstream_write_1(), which writes in chunks.  Otherwise, we
473    repeatedly call Lstream_putc(), which knows how to handle
474    line buffering.  Returns number of bytes written. */
475
476 ssize_t
477 Lstream_write (Lstream *lstr, const void *data, size_t size)
478 {
479   size_t i;
480   const unsigned char *p = (const unsigned char *) data;
481
482   if (size == 0)
483     return size;
484   if (lstr->buffering != LSTREAM_LINE_BUFFERED)
485     return Lstream_write_1 (lstr, data, size);
486   for (i = 0; i < size; i++)
487     {
488       if (Lstream_putc (lstr, p[i]) < 0)
489         break;
490     }
491   return i == 0 ? -1 : (ssize_t) i;
492 }
493
494 int
495 Lstream_was_blocked_p (Lstream *lstr)
496 {
497   return lstr->imp->was_blocked_p ? lstr->imp->was_blocked_p (lstr) : 0;
498 }
499
500 static int
501 Lstream_raw_read (Lstream *lstr, unsigned char *buffer, size_t size)
502 {
503   if (! (lstr->flags & LSTREAM_FL_IS_OPEN))
504     Lstream_internal_error ("lstream not open", lstr);
505   if (! (lstr->flags & LSTREAM_FL_READ))
506     Lstream_internal_error ("lstream not open for reading", lstr);
507   if (!lstr->imp->reader)
508     Lstream_internal_error ("lstream has no reader", lstr);
509
510   return (lstr->imp->reader) (lstr, buffer, size);
511 }
512
513 /* Assuming the buffer is empty, fill it up again. */
514
515 static ssize_t
516 Lstream_read_more (Lstream *lstr)
517 {
518 #if 0
519   ssize_t size_needed = max (1, min (MAX_READ_SIZE, lstr->buffering_size));
520 #else
521   /* If someone requested a larger buffer size, so be it! */
522   ssize_t size_needed = max (1, lstr->buffering_size);
523 #endif
524   ssize_t size_gotten;
525
526   DO_REALLOC (lstr->in_buffer, lstr->in_buffer_size,
527               size_needed, unsigned char);
528   size_gotten = Lstream_raw_read (lstr, lstr->in_buffer, size_needed);
529   lstr->in_buffer_current = max (0, size_gotten);
530   lstr->in_buffer_ind = 0;
531   return size_gotten < 0 ? -1 : size_gotten;
532 }
533
534 ssize_t
535 Lstream_read (Lstream *lstr, void *data, size_t size)
536 {
537   unsigned char *p = (unsigned char *) data;
538   size_t off = 0;
539   size_t chunk;
540   int error_occurred = 0;
541
542   if (size == 0)
543     return 0;
544
545   /* First try to get some data from the unget buffer */
546   chunk = min (size, lstr->unget_buffer_ind);
547   if (chunk > 0)
548     {
549       /* The bytes come back in reverse order. */
550       for (; off < chunk; off++)
551         p[off] = lstr->unget_buffer[--lstr->unget_buffer_ind];
552       lstr->byte_count += chunk;
553       size -= chunk;
554     }
555
556   while (size > 0)
557     {
558       /* Take whatever we can from the in buffer */
559       chunk = min (size, lstr->in_buffer_current - lstr->in_buffer_ind);
560       if (chunk > 0)
561         {
562           memcpy (p + off, lstr->in_buffer + lstr->in_buffer_ind, chunk);
563           lstr->in_buffer_ind += chunk;
564           lstr->byte_count    += chunk;
565           size -= chunk;
566           off  += chunk;
567         }
568
569       /* If we need some more, try to get some more from the stream's end */
570       if (size > 0)
571         {
572           ssize_t retval = Lstream_read_more (lstr);
573           if (retval < 0)
574             error_occurred = 1;
575           if (retval <= 0)
576             break;
577         }
578     }
579
580   /* #### Beware of OFF ending up 0. */
581   if ((lstr->flags & LSTREAM_FL_NO_PARTIAL_CHARS) && off > 0)
582     {
583       /* It's quite possible for us to get passed an incomplete
584          character at the end.  We need to spit back that
585          incomplete character. */
586       const unsigned char *dataend = p + off - 1;
587       /* Optimize the most common case. */
588       if (!BYTE_ASCII_P (*dataend))
589         {
590           /* Go back to the beginning of the last (and possibly partial)
591              character, and bump forward to see if the character is
592              complete. */
593           VALIDATE_CHARPTR_BACKWARD (dataend);
594           if (dataend + REP_BYTES_BY_FIRST_BYTE (*dataend) != p + off)
595             {
596               size_t newoff = dataend - p;
597               /* If not, chop the size down to ignore the last char
598                  and stash it away for next time. */
599               Lstream_unread (lstr, dataend, off - newoff);
600               off = newoff;
601             }
602         }
603     }
604
605   return off == 0 && error_occurred ? -1 : (ssize_t) off;
606 }
607
608 void
609 Lstream_unread (Lstream *lstr, const void *data, size_t size)
610 {
611   const unsigned char *p = (const unsigned char *) data;
612
613   /* Make sure buffer is big enough */
614   DO_REALLOC (lstr->unget_buffer, lstr->unget_buffer_size,
615               lstr->unget_buffer_ind + size, unsigned char);
616
617   lstr->byte_count -= size;
618
619   /* Bytes have to go on in reverse order -- they are reversed
620      again when read back. */
621   while (size--)
622     lstr->unget_buffer[lstr->unget_buffer_ind++] = p[size];
623 }
624
625 int
626 Lstream_rewind (Lstream *lstr)
627 {
628   if (!lstr->imp->rewinder)
629     Lstream_internal_error ("lstream has no rewinder", lstr);
630   if (Lstream_flush (lstr) < 0)
631     return -1;
632   lstr->byte_count = 0;
633   return (lstr->imp->rewinder) (lstr);
634 }
635
636 int
637 Lstream_seekable_p (Lstream *lstr)
638 {
639   if (!lstr->imp->rewinder)
640     return 0;
641   if (!lstr->imp->seekable_p)
642     return 1;
643   return (lstr->imp->seekable_p) (lstr);
644 }
645
646 static int
647 Lstream_pseudo_close (Lstream *lstr)
648 {
649   if (!lstr->flags & LSTREAM_FL_IS_OPEN)
650     Lstream_internal_error ("lstream is not open", lstr);
651
652   /* don't check errors here -- best not to risk file descriptor loss */
653   return Lstream_flush (lstr);
654 }
655
656 int
657 Lstream_close (Lstream *lstr)
658 {
659   int rc = 0;
660
661   if (lstr->flags & LSTREAM_FL_IS_OPEN)
662     {
663       rc = Lstream_pseudo_close (lstr);
664       /*
665        * We used to return immediately if the closer method reported
666        * failure, leaving the stream open.  But this is no good, for
667        * the following reasons.
668        *
669        * 1. The finalizer method used in GC makes no provision for
670        *    failure, so we must not return without freeing buffer
671        *    memory.
672        *
673        * 2. The closer method may have already freed some memory
674        *    used for I/O in this stream.  E.g. encoding_closer frees
675        *    ENCODING_STREAM_DATA(stream)->runoff.  If a writer method
676        *    tries to use this buffer later, it will write into memory
677        *    that may have been allocated elsewhere.  Sometime later
678        *    you will see a sign that says "Welcome to Crash City."
679        *
680        * 3. The closer can report failure if a flush fails in the
681        *    other stream in a MULE encoding/decoding stream pair.
682        *    The other stream in the pair is closed, but returning
683        *    early leaves the current stream open.  If we try to
684        *    flush the current stream later, we will crash when the
685        *    flusher notices that the other end stream is closed.
686        *
687        * So, we no longer abort the close if the closer method
688        * reports some kind of failure.  We still report the failure
689        * to the caller.
690        */
691       if (lstr->imp->closer)
692         if ((lstr->imp->closer) (lstr) < 0)
693           rc = -1;
694     }
695
696   lstr->flags &= ~LSTREAM_FL_IS_OPEN;
697   lstr->byte_count = 0;
698   /* Note that Lstream_flush() reset all the buffer indices.  That way,
699      the next call to Lstream_putc(), Lstream_getc(), or Lstream_ungetc()
700      on a closed stream will call into the function equivalents, which will
701      cause an error. */
702
703   /* We set the pointers to 0 so that we don't lose when this function
704      is called more than once on the same object */
705   if (lstr->out_buffer)
706     {
707       xfree (lstr->out_buffer);
708       lstr->out_buffer = 0;
709     }
710   if (lstr->in_buffer)
711     {
712       xfree (lstr->in_buffer);
713       lstr->in_buffer = 0;
714     }
715   if (lstr->unget_buffer)
716     {
717       xfree (lstr->unget_buffer);
718       lstr->unget_buffer = 0;
719     }
720
721   return rc;
722 }
723
724 int
725 Lstream_fputc (Lstream *lstr, int c)
726 {
727   unsigned char ch = (unsigned char) c;
728   ssize_t retval = Lstream_write_1 (lstr, &ch, 1);
729   if (retval >= 0 && lstr->buffering == LSTREAM_LINE_BUFFERED && ch == '\n')
730     return Lstream_flush_out (lstr);
731   return retval < 0 ? -1 : 0;
732 }
733
734 int
735 Lstream_fgetc (Lstream *lstr)
736 {
737   unsigned char ch;
738   if (Lstream_read (lstr, &ch, 1) <= 0)
739     return -1;
740   return ch;
741 }
742
743 void
744 Lstream_fungetc (Lstream *lstr, int c)
745 {
746   unsigned char ch = (unsigned char) c;
747   Lstream_unread (lstr, &ch, 1);
748 }
749
750 \f
751 /************************ some stream implementations *********************/
752
753 /*********** a stdio stream ***********/
754
755 struct stdio_stream
756 {
757   FILE *file;
758   int closing;
759 };
760
761 #define STDIO_STREAM_DATA(stream) LSTREAM_TYPE_DATA (stream, stdio)
762
763 DEFINE_LSTREAM_IMPLEMENTATION ("stdio", lstream_stdio,
764                                sizeof (struct stdio_stream));
765
766 static Lisp_Object
767 make_stdio_stream_1 (FILE *stream, int flags, const char *mode)
768 {
769   Lisp_Object obj;
770   Lstream *lstr = Lstream_new (lstream_stdio, mode);
771   struct stdio_stream *str = STDIO_STREAM_DATA (lstr);
772   str->file = stream;
773   str->closing = flags & LSTR_CLOSING;
774   lstr->flags |= LSTREAM_FL_CLOSE_AT_DISKSAVE;
775   XSETLSTREAM (obj, lstr);
776   return obj;
777 }
778
779 Lisp_Object
780 make_stdio_input_stream (FILE *stream, int flags)
781 {
782   return make_stdio_stream_1 (stream, flags, "r");
783 }
784
785 Lisp_Object
786 make_stdio_output_stream (FILE *stream, int flags)
787 {
788   return make_stdio_stream_1 (stream, flags, "w");
789 }
790
791 /* #### From reading the Unix 98 specification, it appears that if we
792    want stdio_reader() to be completely correct, we should check for
793    0 < val < size and if so, check to see if an error has occurred.
794    If an error has occurred, but val is non-zero, we should go ahead
795    and act as if the read was successful, but remember in some fashion
796    or other, that an error has occurred, and report that on the next
797    call to stdio_reader instead of calling fread() again.
798
799    Currently, in such a case, we end up calling fread() twice and we
800    assume that
801
802    1) this is not harmful, and
803    2) the error will still be reported on the second read.
804
805    This is probably reasonable, so I don't think we should change this
806    code (it could even be argued that the error might have fixed
807    itself, so we should do the fread() again.  */
808
809 static ssize_t
810 stdio_reader (Lstream *stream, unsigned char *data, size_t size)
811 {
812   struct stdio_stream *str = STDIO_STREAM_DATA (stream);
813   size_t val = fread (data, 1, size, str->file);
814   if (!val && ferror (str->file))
815     return -1;
816   return val;
817 }
818
819 static ssize_t
820 stdio_writer (Lstream *stream, const unsigned char *data, size_t size)
821 {
822   struct stdio_stream *str = STDIO_STREAM_DATA (stream);
823   size_t val = fwrite (data, 1, size, str->file);
824   if (!val && ferror (str->file))
825     return -1;
826   return val;
827 }
828
829 static int
830 stdio_rewinder (Lstream *stream)
831 {
832   rewind (STDIO_STREAM_DATA (stream)->file);
833   return 0;
834 }
835
836 static int
837 stdio_seekable_p (Lstream *stream)
838 {
839   struct stat lestat;
840   struct stdio_stream *str = STDIO_STREAM_DATA (stream);
841
842   if (fstat (fileno (str->file), &lestat) < 0)
843     return 0;
844   return S_ISREG (lestat.st_mode);
845 }
846
847 static int
848 stdio_flusher (Lstream *stream)
849 {
850   struct stdio_stream *str = STDIO_STREAM_DATA (stream);
851   if (stream->flags & LSTREAM_FL_WRITE)
852     return fflush (str->file);
853   else
854     return 0;
855 }
856
857 static int
858 stdio_closer (Lstream *stream)
859 {
860   struct stdio_stream *str = STDIO_STREAM_DATA (stream);
861   if (str->closing)
862     return fclose (str->file);
863   else
864   if (stream->flags & LSTREAM_FL_WRITE)
865     return fflush (str->file);
866   else
867     return 0;
868 }
869
870 /*********** a file descriptor ***********/
871
872 struct filedesc_stream
873 {
874   int fd;
875   int pty_max_bytes;
876   Bufbyte eof_char;
877   int starting_pos;
878   int current_pos;
879   int end_pos;
880   int chars_sans_newline;
881   unsigned int closing :1;
882   unsigned int allow_quit :1;
883   unsigned int blocked_ok :1;
884   unsigned int pty_flushing :1;
885   unsigned int blocking_error_p :1;
886 };
887
888 #define FILEDESC_STREAM_DATA(stream) LSTREAM_TYPE_DATA (stream, filedesc)
889
890 DEFINE_LSTREAM_IMPLEMENTATION ("filedesc", lstream_filedesc,
891                                sizeof (struct filedesc_stream));
892
893 /* Make a stream that reads from or writes to a file descriptor FILEDESC.
894    OFFSET is the offset from the *current* file pointer that the reading
895    should start at.  COUNT is the number of bytes to be read (it is
896    ignored when writing); -1 for unlimited. */
897 static Lisp_Object
898 make_filedesc_stream_1 (int filedesc, int offset, int count, int flags,
899                         const char *mode)
900 {
901   Lisp_Object obj;
902   Lstream *lstr = Lstream_new (lstream_filedesc, mode);
903   struct filedesc_stream *fstr = FILEDESC_STREAM_DATA (lstr);
904   fstr->fd = filedesc;
905   fstr->closing      = !!(flags & LSTR_CLOSING);
906   fstr->allow_quit   = !!(flags & LSTR_ALLOW_QUIT);
907   fstr->blocked_ok   = !!(flags & LSTR_BLOCKED_OK);
908   fstr->pty_flushing = !!(flags & LSTR_PTY_FLUSHING);
909   fstr->blocking_error_p = 0;
910   fstr->chars_sans_newline = 0;
911   fstr->starting_pos = lseek (filedesc, offset, SEEK_CUR);
912   fstr->current_pos = max (fstr->starting_pos, 0);
913   if (count < 0)
914     fstr->end_pos = -1;
915   else
916     fstr->end_pos = fstr->starting_pos + count;
917   lstr->flags |= LSTREAM_FL_CLOSE_AT_DISKSAVE;
918   XSETLSTREAM (obj, lstr);
919   return obj;
920 }
921
922 Lisp_Object
923 make_filedesc_input_stream (int filedesc, int offset, int count, int flags)
924 {
925   return make_filedesc_stream_1 (filedesc, offset, count, flags, "r");
926 }
927
928 Lisp_Object
929 make_filedesc_output_stream (int filedesc, int offset, int count, int flags)
930 {
931   return make_filedesc_stream_1 (filedesc, offset, count, flags, "w");
932 }
933
934 static ssize_t
935 filedesc_reader (Lstream *stream, unsigned char *data, size_t size)
936 {
937   ssize_t nread;
938   struct filedesc_stream *str = FILEDESC_STREAM_DATA (stream);
939   if (str->end_pos >= 0)
940     size = min (size, (size_t) (str->end_pos - str->current_pos));
941   nread = str->allow_quit ?
942     read_allowing_quit (str->fd, data, size) :
943     read (str->fd, data, size);
944   if (nread > 0)
945     str->current_pos += nread;
946   return nread;
947 }
948
949 static int
950 errno_would_block_p (int val)
951 {
952 #ifdef EWOULDBLOCK
953   if (val == EWOULDBLOCK)
954     return 1;
955 #endif
956 #ifdef EAGAIN
957   if (val == EAGAIN)
958     return 1;
959 #endif
960   return 0;
961 }
962
963 static ssize_t
964 filedesc_writer (Lstream *stream, const unsigned char *data, size_t size)
965 {
966   struct filedesc_stream *str = FILEDESC_STREAM_DATA (stream);
967   ssize_t retval;
968   int need_newline = 0;
969
970   /* This function would be simple if it were not for the blasted
971      PTY max-bytes stuff.  Why the hell can't they just have written
972      the PTY drivers right so this problem doesn't exist?
973
974      Maybe all the PTY crap here should be moved into another stream
975      that does nothing but periodically insert EOF's as necessary. */
976   if (str->pty_flushing)
977     {
978       /* To make life easy, only send out one line at the most. */
979       const unsigned char *ptr;
980
981       ptr = (const unsigned char *) memchr (data, '\n', size);
982       if (ptr)
983         need_newline = 1;
984       else
985         ptr = data + size;
986       if (ptr - data >= str->pty_max_bytes - str->chars_sans_newline)
987         {
988           ptr = data + str->pty_max_bytes - str->chars_sans_newline;
989           need_newline = 0;
990         }
991       size = ptr - data;
992     }
993
994   /**** start of non-PTY-crap ****/
995   if (size > 0)
996     retval = str->allow_quit ?
997       write_allowing_quit (str->fd, data, size) :
998       write (str->fd, data, size);
999   else
1000     retval = 0;
1001   if (retval < 0 && errno_would_block_p (errno) && str->blocked_ok)
1002     {
1003       str->blocking_error_p = 1;
1004       return 0;
1005     }
1006   str->blocking_error_p = 0;
1007   if (retval < 0)
1008     return retval;
1009   /**** end non-PTY-crap ****/
1010
1011   if (str->pty_flushing)
1012     {
1013       str->chars_sans_newline += retval;
1014       /* Note that a newline was not among the bytes written out.
1015          Add to the number of non-newline bytes written out,
1016          and flush with an EOF if necessary.  Be careful to
1017          keep track of write errors as we go along and look
1018          out for EWOULDBLOCK. */
1019       if (str->chars_sans_newline >= str->pty_max_bytes)
1020         {
1021           ssize_t retval2 = str->allow_quit ?
1022             write_allowing_quit (str->fd, &str->eof_char, 1) :
1023             write (str->fd, &str->eof_char, 1);
1024
1025           if (retval2 > 0)
1026             str->chars_sans_newline = 0;
1027           else if (retval2 < 0)
1028             {
1029               /* Error writing the EOF char.  If nothing got written,
1030                  then treat this as an error -- either return an error
1031                  condition or set the blocking-error flag. */
1032               if (retval == 0)
1033                 {
1034                   if (errno_would_block_p (errno) && str->blocked_ok)
1035                     {
1036                       str->blocking_error_p = 1;
1037                       return 0;
1038                     }
1039                   else
1040                     return retval2;
1041                 }
1042               else
1043                 return retval;
1044             }
1045         }
1046     }
1047
1048   /* The need_newline flag is necessary because otherwise when the
1049      first byte is a newline, we'd get stuck never writing anything
1050      in pty-flushing mode. */
1051   if (need_newline)
1052     {
1053       Bufbyte nl = '\n';
1054       ssize_t retval2 = str->allow_quit ?
1055         write_allowing_quit (str->fd, &nl, 1) :
1056         write (str->fd, &nl, 1);
1057
1058       if (retval2 > 0)
1059         {
1060           str->chars_sans_newline = 0;
1061           retval++;
1062         }
1063       else if (retval2 < 0)
1064         {
1065           /* Error writing the newline char.  If nothing got written,
1066              then treat this as an error -- either return an error
1067              condition or set the blocking-error flag. */
1068           if (retval == 0)
1069             {
1070               if (errno_would_block_p (errno) && str->blocked_ok)
1071                 {
1072                   str->blocking_error_p = 1;
1073                   return 0;
1074                 }
1075               else
1076                 return retval2;
1077             }
1078           else
1079             return retval;
1080         }
1081     }
1082
1083   return retval;
1084 }
1085
1086 static int
1087 filedesc_rewinder (Lstream *stream)
1088 {
1089   struct filedesc_stream *str = FILEDESC_STREAM_DATA (stream);
1090   if (str->starting_pos < 0 ||
1091       lseek (FILEDESC_STREAM_DATA (stream)->fd, str->starting_pos,
1092              SEEK_SET) == -1)
1093     return -1;
1094   else
1095     {
1096       str->current_pos = str->starting_pos;
1097       return 0;
1098     }
1099 }
1100
1101 static int
1102 filedesc_seekable_p (Lstream *stream)
1103 {
1104   struct filedesc_stream *str = FILEDESC_STREAM_DATA (stream);
1105   if (str->starting_pos < 0)
1106     return 0;
1107   else
1108     {
1109       struct stat lestat;
1110
1111       if (fstat (str->fd, &lestat) < 0)
1112         return 0;
1113       return S_ISREG (lestat.st_mode);
1114     }
1115 }
1116
1117 static int
1118 filedesc_closer (Lstream *stream)
1119 {
1120   struct filedesc_stream *str = FILEDESC_STREAM_DATA (stream);
1121   if (str->closing)
1122     return close (str->fd);
1123   else
1124     return 0;
1125 }
1126
1127 static int
1128 filedesc_was_blocked_p (Lstream *stream)
1129 {
1130   struct filedesc_stream *str = FILEDESC_STREAM_DATA (stream);
1131   return str->blocking_error_p;
1132 }
1133
1134 void
1135 filedesc_stream_set_pty_flushing (Lstream *stream, int pty_max_bytes,
1136                                   Bufbyte eof_char)
1137 {
1138   struct filedesc_stream *str = FILEDESC_STREAM_DATA (stream);
1139   str->pty_max_bytes = pty_max_bytes;
1140   str->eof_char = eof_char;
1141   str->pty_flushing = 1;
1142 }
1143
1144 int
1145 filedesc_stream_fd (Lstream *stream)
1146 {
1147   struct filedesc_stream *str = FILEDESC_STREAM_DATA (stream);
1148   return str->fd;
1149 }
1150
1151 /*********** read from a Lisp string ***********/
1152
1153 #define LISP_STRING_STREAM_DATA(stream) LSTREAM_TYPE_DATA (stream, lisp_string)
1154
1155 struct lisp_string_stream
1156 {
1157   Lisp_Object obj;
1158   Bytecount init_offset;
1159   Bytecount offset, end;
1160 };
1161
1162 DEFINE_LSTREAM_IMPLEMENTATION ("lisp-string", lstream_lisp_string,
1163                                sizeof (struct lisp_string_stream));
1164
1165 Lisp_Object
1166 make_lisp_string_input_stream (Lisp_Object string, Bytecount offset,
1167                                Bytecount len)
1168 {
1169   Lisp_Object obj;
1170   Lstream *lstr;
1171   struct lisp_string_stream *str;
1172
1173   CHECK_STRING (string);
1174   if (len < 0)
1175     len = XSTRING_LENGTH (string) - offset;
1176   assert (offset >= 0);
1177   assert (len >= 0);
1178   assert (offset + len <= XSTRING_LENGTH (string));
1179
1180   lstr = Lstream_new (lstream_lisp_string, "r");
1181   str = LISP_STRING_STREAM_DATA (lstr);
1182   str->offset = offset;
1183   str->end = offset + len;
1184   str->init_offset = offset;
1185   str->obj = string;
1186   XSETLSTREAM (obj, lstr);
1187   return obj;
1188 }
1189
1190 static ssize_t
1191 lisp_string_reader (Lstream *stream, unsigned char *data, size_t size)
1192 {
1193   struct lisp_string_stream *str = LISP_STRING_STREAM_DATA (stream);
1194   /* Don't lose if the string shrank past us ... */
1195   Bytecount offset = min (str->offset, XSTRING_LENGTH (str->obj));
1196   Bufbyte *strstart = XSTRING_DATA (str->obj);
1197   Bufbyte *start = strstart + offset;
1198
1199   /* ... or if someone changed the string and we ended up in the
1200      middle of a character. */
1201   /* Being in the middle of a character is `normal' unless
1202      LSTREAM_NO_PARTIAL_CHARS - mrb */
1203   if (stream->flags & LSTREAM_FL_NO_PARTIAL_CHARS)
1204     VALIDATE_CHARPTR_BACKWARD (start);
1205   offset = start - strstart;
1206   size = min (size, (size_t) (str->end - offset));
1207   memcpy (data, start, size);
1208   str->offset = offset + size;
1209   return size;
1210 }
1211
1212 static int
1213 lisp_string_rewinder (Lstream *stream)
1214 {
1215   struct lisp_string_stream *str = LISP_STRING_STREAM_DATA (stream);
1216   int pos = str->init_offset;
1217   if (pos > str->end)
1218     pos = str->end;
1219   /* Don't lose if the string shrank past us ... */
1220   pos = min (pos, XSTRING_LENGTH (str->obj));
1221   /* ... or if someone changed the string and we ended up in the
1222      middle of a character. */
1223   {
1224     Bufbyte *strstart = XSTRING_DATA (str->obj);
1225     Bufbyte *start = strstart + pos;
1226     VALIDATE_CHARPTR_BACKWARD (start);
1227     pos = start - strstart;
1228   }
1229   str->offset = pos;
1230   return 0;
1231 }
1232
1233 static Lisp_Object
1234 lisp_string_marker (Lisp_Object stream)
1235 {
1236   struct lisp_string_stream *str = LISP_STRING_STREAM_DATA (XLSTREAM (stream));
1237   return str->obj;
1238 }
1239
1240 /*********** a fixed buffer ***********/
1241
1242 #define FIXED_BUFFER_STREAM_DATA(stream) \
1243   LSTREAM_TYPE_DATA (stream, fixed_buffer)
1244
1245 struct fixed_buffer_stream
1246 {
1247   const unsigned char *inbuf;
1248   unsigned char *outbuf;
1249   size_t size;
1250   size_t offset;
1251 };
1252
1253 DEFINE_LSTREAM_IMPLEMENTATION ("fixed-buffer", lstream_fixed_buffer,
1254                                sizeof (struct fixed_buffer_stream));
1255
1256 Lisp_Object
1257 make_fixed_buffer_input_stream (const void *buf, size_t size)
1258 {
1259   Lisp_Object obj;
1260   Lstream *lstr = Lstream_new (lstream_fixed_buffer, "r");
1261   struct fixed_buffer_stream *str = FIXED_BUFFER_STREAM_DATA (lstr);
1262   str->inbuf = (const unsigned char *) buf;
1263   str->size = size;
1264   XSETLSTREAM (obj, lstr);
1265   return obj;
1266 }
1267
1268 Lisp_Object
1269 make_fixed_buffer_output_stream (void *buf, size_t size)
1270 {
1271   Lisp_Object obj;
1272   Lstream *lstr = Lstream_new (lstream_fixed_buffer, "w");
1273   struct fixed_buffer_stream *str = FIXED_BUFFER_STREAM_DATA (lstr);
1274   str->outbuf = (unsigned char *) buf;
1275   str->size = size;
1276   XSETLSTREAM (obj, lstr);
1277   return obj;
1278 }
1279
1280 static ssize_t
1281 fixed_buffer_reader (Lstream *stream, unsigned char *data, size_t size)
1282 {
1283   struct fixed_buffer_stream *str = FIXED_BUFFER_STREAM_DATA (stream);
1284   size = min (size, str->size - str->offset);
1285   memcpy (data, str->inbuf + str->offset, size);
1286   str->offset += size;
1287   return size;
1288 }
1289
1290 static ssize_t
1291 fixed_buffer_writer (Lstream *stream, const unsigned char *data, size_t size)
1292 {
1293   struct fixed_buffer_stream *str = FIXED_BUFFER_STREAM_DATA (stream);
1294   if (str->offset == str->size)
1295     {
1296       /* If we're at the end, just throw away the data and pretend
1297          we wrote all of it.  If we return 0, then the lstream routines
1298          will try again and again to write it out. */
1299       return size;
1300     }
1301   size = min (size, str->size - str->offset);
1302   memcpy (str->outbuf + str->offset, data, size);
1303   str->offset += size;
1304   return size;
1305 }
1306
1307 static int
1308 fixed_buffer_rewinder (Lstream *stream)
1309 {
1310   FIXED_BUFFER_STREAM_DATA (stream)->offset = 0;
1311   return 0;
1312 }
1313
1314 const unsigned char *
1315 fixed_buffer_input_stream_ptr (Lstream *stream)
1316 {
1317   assert (stream->imp == lstream_fixed_buffer);
1318   return FIXED_BUFFER_STREAM_DATA (stream)->inbuf;
1319 }
1320
1321 unsigned char *
1322 fixed_buffer_output_stream_ptr (Lstream *stream)
1323 {
1324   assert (stream->imp == lstream_fixed_buffer);
1325   return FIXED_BUFFER_STREAM_DATA (stream)->outbuf;
1326 }
1327
1328 /*********** write to a resizing buffer ***********/
1329
1330 #define RESIZING_BUFFER_STREAM_DATA(stream) \
1331   LSTREAM_TYPE_DATA (stream, resizing_buffer)
1332
1333 struct resizing_buffer_stream
1334 {
1335   unsigned char *buf;
1336   size_t allocked;
1337   int max_stored;
1338   int stored;
1339 };
1340
1341 DEFINE_LSTREAM_IMPLEMENTATION ("resizing-buffer", lstream_resizing_buffer,
1342                                sizeof (struct resizing_buffer_stream));
1343
1344 Lisp_Object
1345 make_resizing_buffer_output_stream (void)
1346 {
1347   Lisp_Object obj;
1348   XSETLSTREAM (obj, Lstream_new (lstream_resizing_buffer, "w"));
1349   return obj;
1350 }
1351
1352 static ssize_t
1353 resizing_buffer_writer (Lstream *stream, const unsigned char *data, size_t size)
1354 {
1355   struct resizing_buffer_stream *str = RESIZING_BUFFER_STREAM_DATA (stream);
1356   DO_REALLOC (str->buf, str->allocked, str->stored + size, unsigned char);
1357   memcpy (str->buf + str->stored, data, size);
1358   str->stored += size;
1359   str->max_stored = max (str->max_stored, str->stored);
1360   return size;
1361 }
1362
1363 static int
1364 resizing_buffer_rewinder (Lstream *stream)
1365 {
1366   RESIZING_BUFFER_STREAM_DATA (stream)->stored = 0;
1367   return 0;
1368 }
1369
1370 static int
1371 resizing_buffer_closer (Lstream *stream)
1372 {
1373   struct resizing_buffer_stream *str = RESIZING_BUFFER_STREAM_DATA (stream);
1374   if (str->buf)
1375     {
1376       xfree (str->buf);
1377       str->buf = 0;
1378     }
1379   return 0;
1380 }
1381
1382 unsigned char *
1383 resizing_buffer_stream_ptr (Lstream *stream)
1384 {
1385   return RESIZING_BUFFER_STREAM_DATA (stream)->buf;
1386 }
1387
1388 /*********** write to an unsigned-char dynarr ***********/
1389
1390 /* Note: If you have a dynarr whose type is not unsigned_char_dynarr
1391    but which is really just an unsigned_char_dynarr (e.g. its type
1392    is Bufbyte or Extbyte), just cast to unsigned_char_dynarr. */
1393
1394 #define DYNARR_STREAM_DATA(stream) \
1395   LSTREAM_TYPE_DATA (stream, dynarr)
1396
1397 struct dynarr_stream
1398 {
1399   unsigned_char_dynarr *dyn;
1400 };
1401
1402 DEFINE_LSTREAM_IMPLEMENTATION ("dynarr", lstream_dynarr,
1403                                sizeof (struct dynarr_stream));
1404
1405 Lisp_Object
1406 make_dynarr_output_stream (unsigned_char_dynarr *dyn)
1407 {
1408   Lisp_Object obj;
1409   XSETLSTREAM (obj, Lstream_new (lstream_dynarr, "w"));
1410   DYNARR_STREAM_DATA (XLSTREAM (obj))->dyn = dyn;
1411   return obj;
1412 }
1413
1414 static ssize_t
1415 dynarr_writer (Lstream *stream, const unsigned char *data, size_t size)
1416 {
1417   struct dynarr_stream *str = DYNARR_STREAM_DATA (stream);
1418   Dynarr_add_many (str->dyn, data, size);
1419   return size;
1420 }
1421
1422 static int
1423 dynarr_rewinder (Lstream *stream)
1424 {
1425   Dynarr_reset (DYNARR_STREAM_DATA (stream)->dyn);
1426   return 0;
1427 }
1428
1429 static int
1430 dynarr_closer (Lstream *stream)
1431 {
1432   return 0;
1433 }
1434
1435 /************ read from or write to a Lisp buffer ************/
1436
1437 /* Note: Lisp-buffer read streams never return partial characters,
1438    and Lisp-buffer write streams expect to never get partial
1439    characters. */
1440
1441 #define LISP_BUFFER_STREAM_DATA(stream) \
1442   LSTREAM_TYPE_DATA (stream, lisp_buffer)
1443
1444 struct lisp_buffer_stream
1445 {
1446   Lisp_Object buffer;
1447   Lisp_Object orig_start;
1448   /* we use markers to properly deal with insertion/deletion */
1449   Lisp_Object start, end;
1450   int flags;
1451 };
1452
1453 DEFINE_LSTREAM_IMPLEMENTATION ("lisp-buffer", lstream_lisp_buffer,
1454                                sizeof (struct lisp_buffer_stream));
1455
1456 static Lisp_Object
1457 make_lisp_buffer_stream_1 (struct buffer *buf, Bufpos start, Bufpos end,
1458                            int flags, const char *mode)
1459 {
1460   Lisp_Object obj;
1461   Lstream *lstr;
1462   struct lisp_buffer_stream *str;
1463   Bufpos bmin, bmax;
1464   int reading = !strcmp (mode, "r");
1465
1466   /* Make sure the luser didn't pass "w" in. */
1467   if (!strcmp (mode, "w"))
1468     abort ();
1469
1470   if (flags & LSTR_IGNORE_ACCESSIBLE)
1471     {
1472       bmin = BUF_BEG (buf);
1473       bmax = BUF_Z (buf);
1474     }
1475   else
1476     {
1477       bmin = BUF_BEGV (buf);
1478       bmax = BUF_ZV (buf);
1479     }
1480
1481   if (start == -1)
1482     start = bmin;
1483   if (end == -1)
1484     end = bmax;
1485   assert (bmin <= start);
1486   assert (start <= bmax);
1487   if (reading)
1488     {
1489       assert (bmin  <= end);
1490       assert (end   <= bmax);
1491       assert (start <= end);
1492     }
1493
1494   lstr = Lstream_new (lstream_lisp_buffer, mode);
1495   str = LISP_BUFFER_STREAM_DATA (lstr);
1496   {
1497     Lisp_Object marker;
1498     Lisp_Object buffer;
1499
1500     XSETBUFFER (buffer, buf);
1501     marker = Fmake_marker ();
1502     Fset_marker (marker, make_int (start), buffer);
1503     str->start = marker;
1504     marker = Fmake_marker ();
1505     Fset_marker (marker, make_int (start), buffer);
1506     str->orig_start = marker;
1507     if (reading)
1508       {
1509         marker = Fmake_marker ();
1510         Fset_marker (marker, make_int (end), buffer);
1511         str->end = marker;
1512       }
1513     else
1514       str->end = Qnil;
1515     str->buffer = buffer;
1516   }
1517   str->flags = flags;
1518   XSETLSTREAM (obj, lstr);
1519   return obj;
1520 }
1521
1522 Lisp_Object
1523 make_lisp_buffer_input_stream (struct buffer *buf, Bufpos start, Bufpos end,
1524                                int flags)
1525 {
1526   return make_lisp_buffer_stream_1 (buf, start, end, flags, "r");
1527 }
1528
1529 Lisp_Object
1530 make_lisp_buffer_output_stream (struct buffer *buf, Bufpos pos, int flags)
1531 {
1532   Lisp_Object lstr = make_lisp_buffer_stream_1 (buf, pos, 0, flags, "wc");
1533
1534   Lstream_set_character_mode (XLSTREAM (lstr));
1535   return lstr;
1536 }
1537
1538 static ssize_t
1539 lisp_buffer_reader (Lstream *stream, unsigned char *data, size_t size)
1540 {
1541   struct lisp_buffer_stream *str = LISP_BUFFER_STREAM_DATA (stream);
1542   unsigned char *orig_data = data;
1543   Bytind start;
1544   Bytind end;
1545   struct buffer *buf = XBUFFER (str->buffer);
1546
1547   if (!BUFFER_LIVE_P (buf))
1548     return 0; /* Fut. */
1549
1550   /* NOTE: We do all our operations in Bytind's.
1551      Keep in mind that SIZE is a value in bytes, not chars. */
1552
1553   start = bi_marker_position (str->start);
1554   end = bi_marker_position (str->end);
1555   if (!(str->flags & LSTR_IGNORE_ACCESSIBLE))
1556     {
1557       start = bytind_clip_to_bounds (BI_BUF_BEGV (buf), start,
1558                                      BI_BUF_ZV (buf));
1559       end = bytind_clip_to_bounds (BI_BUF_BEGV (buf), end,
1560                                    BI_BUF_ZV (buf));
1561     }
1562
1563   size = min (size, (size_t) (end - start));
1564   end = start + size;
1565   /* We cannot return a partial character. */
1566   VALIDATE_BYTIND_BACKWARD (buf, end);
1567
1568   while (start < end)
1569     {
1570       Bytind ceil;
1571       Bytecount chunk;
1572
1573       if (str->flags & LSTR_IGNORE_ACCESSIBLE)
1574         ceil = BI_BUF_CEILING_OF_IGNORE_ACCESSIBLE (buf, start);
1575       else
1576         ceil = BI_BUF_CEILING_OF (buf, start);
1577       chunk = min (ceil, end) - start;
1578       memcpy (data, BI_BUF_BYTE_ADDRESS (buf, start), chunk);
1579       data += chunk;
1580       start += chunk;
1581     }
1582
1583   if (EQ (buf->selective_display, Qt) && str->flags & LSTR_SELECTIVE)
1584     {
1585       /* What a kludge.  What a kludge.  What a kludge. */
1586       unsigned char *p;
1587       for (p = orig_data; p < data; p++)
1588         if (*p == '\r')
1589           *p = '\n';
1590     }
1591
1592   set_bi_marker_position (str->start, end);
1593   return data - orig_data;
1594 }
1595
1596 static ssize_t
1597 lisp_buffer_writer (Lstream *stream, const unsigned char *data, size_t size)
1598 {
1599   struct lisp_buffer_stream *str = LISP_BUFFER_STREAM_DATA (stream);
1600   Bufpos pos;
1601   struct buffer *buf = XBUFFER (str->buffer);
1602
1603   if (!BUFFER_LIVE_P (buf))
1604     return 0; /* Fut. */
1605
1606   pos = marker_position (str->start);
1607   pos += buffer_insert_raw_string_1 (buf, pos, data, size, 0);
1608   set_marker_position (str->start, pos);
1609   return size;
1610 }
1611
1612 static int
1613 lisp_buffer_rewinder (Lstream *stream)
1614 {
1615   struct lisp_buffer_stream *str =
1616     LISP_BUFFER_STREAM_DATA (stream);
1617   struct buffer *buf = XBUFFER (str->buffer);
1618   long pos = marker_position (str->orig_start);
1619   if (!BUFFER_LIVE_P (buf))
1620     return -1; /* Fut. */
1621   if (pos > BUF_ZV (buf))
1622     pos = BUF_ZV (buf);
1623   if (pos < marker_position (str->orig_start))
1624     pos = marker_position (str->orig_start);
1625   if (MARKERP (str->end) && pos > marker_position (str->end))
1626     pos = marker_position (str->end);
1627   set_marker_position (str->start, pos);
1628   return 0;
1629 }
1630
1631 static Lisp_Object
1632 lisp_buffer_marker (Lisp_Object stream)
1633 {
1634   struct lisp_buffer_stream *str =
1635     LISP_BUFFER_STREAM_DATA (XLSTREAM (stream));
1636
1637   mark_object (str->start);
1638   mark_object (str->end);
1639   return str->buffer;
1640 }
1641
1642 Bufpos
1643 lisp_buffer_stream_startpos (Lstream *stream)
1644 {
1645   return marker_position (LISP_BUFFER_STREAM_DATA (stream)->start);
1646 }
1647
1648 \f
1649 /************************************************************************/
1650 /*                            initialization                            */
1651 /************************************************************************/
1652
1653 void
1654 lstream_type_create (void)
1655 {
1656   LSTREAM_HAS_METHOD (stdio, reader);
1657   LSTREAM_HAS_METHOD (stdio, writer);
1658   LSTREAM_HAS_METHOD (stdio, rewinder);
1659   LSTREAM_HAS_METHOD (stdio, seekable_p);
1660   LSTREAM_HAS_METHOD (stdio, flusher);
1661   LSTREAM_HAS_METHOD (stdio, closer);
1662
1663   LSTREAM_HAS_METHOD (filedesc, reader);
1664   LSTREAM_HAS_METHOD (filedesc, writer);
1665   LSTREAM_HAS_METHOD (filedesc, was_blocked_p);
1666   LSTREAM_HAS_METHOD (filedesc, rewinder);
1667   LSTREAM_HAS_METHOD (filedesc, seekable_p);
1668   LSTREAM_HAS_METHOD (filedesc, closer);
1669
1670   LSTREAM_HAS_METHOD (lisp_string, reader);
1671   LSTREAM_HAS_METHOD (lisp_string, rewinder);
1672   LSTREAM_HAS_METHOD (lisp_string, marker);
1673
1674   LSTREAM_HAS_METHOD (fixed_buffer, reader);
1675   LSTREAM_HAS_METHOD (fixed_buffer, writer);
1676   LSTREAM_HAS_METHOD (fixed_buffer, rewinder);
1677
1678   LSTREAM_HAS_METHOD (resizing_buffer, writer);
1679   LSTREAM_HAS_METHOD (resizing_buffer, rewinder);
1680   LSTREAM_HAS_METHOD (resizing_buffer, closer);
1681
1682   LSTREAM_HAS_METHOD (dynarr, writer);
1683   LSTREAM_HAS_METHOD (dynarr, rewinder);
1684   LSTREAM_HAS_METHOD (dynarr, closer);
1685
1686   LSTREAM_HAS_METHOD (lisp_buffer, reader);
1687   LSTREAM_HAS_METHOD (lisp_buffer, writer);
1688   LSTREAM_HAS_METHOD (lisp_buffer, rewinder);
1689   LSTREAM_HAS_METHOD (lisp_buffer, marker);
1690 }
1691
1692 void
1693 reinit_vars_of_lstream (void)
1694 {
1695   int i;
1696
1697   for (i = 0; i < countof (Vlstream_free_list); i++)
1698     {
1699       Vlstream_free_list[i] = Qnil;
1700       staticpro_nodump (&Vlstream_free_list[i]);
1701     }
1702 }
1703
1704 void
1705 vars_of_lstream (void)
1706 {
1707   INIT_LRECORD_IMPLEMENTATION (lstream);
1708
1709   reinit_vars_of_lstream ();
1710 }