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