XEmacs 21.2.30 "Hygeia".
[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   size_t size = num + lstr->out_buffer_ind;
396
397   if (size <= lstr->out_buffer_size)
398     return num;
399
400   /* Maybe chop it down so that we don't buffer more characters
401      than our advertised buffering size. */
402   if ((size > lstr->buffering_size) && !force)
403     {
404       size = lstr->buffering_size;
405       /* There might be more data buffered than the buffering size. */
406       if (size <= lstr->out_buffer_ind)
407         return 0;
408     }
409
410   DO_REALLOC (lstr->out_buffer, lstr->out_buffer_size, size, unsigned char);
411
412   return size - lstr->out_buffer_ind;
413 }
414
415 /* Like Lstream_write(), but does not handle line-buffering correctly. */
416
417 static ssize_t
418 Lstream_write_1 (Lstream *lstr, const void *data, size_t size)
419 {
420   const unsigned char *p = (const unsigned char *) data;
421   ssize_t off = 0;
422   if (! (lstr->flags & LSTREAM_FL_IS_OPEN))
423     Lstream_internal_error ("lstream not open", lstr);
424   if (! (lstr->flags & LSTREAM_FL_WRITE))
425     Lstream_internal_error ("lstream not open for writing", lstr);
426   {
427     int couldnt_write_last_time = 0;
428
429     while (1)
430       {
431         /* Figure out how much we can add to the buffer */
432         size_t chunk = Lstream_adding (lstr, size, 0);
433         if (chunk == 0)
434           {
435             if (couldnt_write_last_time)
436               /* Ung, we ran out of space and tried to flush
437                  the buffer, but it didn't work because the stream
438                  writer is refusing to accept any data.  So we
439                  just have to squirrel away all the rest of the
440                  stuff. */
441               chunk = Lstream_adding (lstr, size, 1);
442             else
443               couldnt_write_last_time = 1;
444           }
445         /* Do it. */
446         if (chunk > 0)
447           {
448             memcpy (lstr->out_buffer + lstr->out_buffer_ind, p + off, chunk);
449             lstr->out_buffer_ind += chunk;
450             lstr->byte_count     += chunk;
451             size -= chunk;
452             off  += chunk;
453           }
454         /* If the buffer is full and we have more to add, flush it out. */
455         if (size > 0)
456           {
457             if (Lstream_flush_out (lstr) < 0)
458               {
459                 if (off == 0)
460                   return -1;
461                 else
462                   return off;
463               }
464           }
465         else
466           break;
467       }
468   }
469   return off;
470 }
471
472 /* If the stream is not line-buffered, then we can just call
473    Lstream_write_1(), which writes in chunks.  Otherwise, we
474    repeatedly call Lstream_putc(), which knows how to handle
475    line buffering.  Returns number of bytes written. */
476
477 ssize_t
478 Lstream_write (Lstream *lstr, const void *data, size_t size)
479 {
480   size_t i;
481   const unsigned char *p = (const unsigned char *) data;
482
483   if (size == 0)
484     return size;
485   if (lstr->buffering != LSTREAM_LINE_BUFFERED)
486     return Lstream_write_1 (lstr, data, size);
487   for (i = 0; i < size; i++)
488     {
489       if (Lstream_putc (lstr, p[i]) < 0)
490         break;
491     }
492   return i == 0 ? -1 : (ssize_t) i;
493 }
494
495 int
496 Lstream_was_blocked_p (Lstream *lstr)
497 {
498   return lstr->imp->was_blocked_p ? lstr->imp->was_blocked_p (lstr) : 0;
499 }
500
501 static int
502 Lstream_raw_read (Lstream *lstr, unsigned char *buffer, size_t size)
503 {
504   if (! (lstr->flags & LSTREAM_FL_IS_OPEN))
505     Lstream_internal_error ("lstream not open", lstr);
506   if (! (lstr->flags & LSTREAM_FL_READ))
507     Lstream_internal_error ("lstream not open for reading", lstr);
508   if (!lstr->imp->reader)
509     Lstream_internal_error ("lstream has no reader", lstr);
510
511   return (lstr->imp->reader) (lstr, buffer, size);
512 }
513
514 /* Assuming the buffer is empty, fill it up again. */
515
516 static ssize_t
517 Lstream_read_more (Lstream *lstr)
518 {
519 #if 0
520   ssize_t size_needed = max (1, min (MAX_READ_SIZE, lstr->buffering_size));
521 #else
522   /* If someone requested a larger buffer size, so be it! */
523   ssize_t size_needed = max (1, lstr->buffering_size);
524 #endif
525   ssize_t size_gotten;
526
527   DO_REALLOC (lstr->in_buffer, lstr->in_buffer_size,
528               size_needed, unsigned char);
529   size_gotten = Lstream_raw_read (lstr, lstr->in_buffer, size_needed);
530   lstr->in_buffer_current = max (0, size_gotten);
531   lstr->in_buffer_ind = 0;
532   return size_gotten < 0 ? -1 : size_gotten;
533 }
534
535 ssize_t
536 Lstream_read (Lstream *lstr, void *data, size_t size)
537 {
538   unsigned char *p = (unsigned char *) data;
539   size_t off = 0;
540   size_t chunk;
541   int error_occurred = 0;
542
543   if (size == 0)
544     return 0;
545
546   /* First try to get some data from the unget buffer */
547   chunk = min (size, lstr->unget_buffer_ind);
548   if (chunk > 0)
549     {
550       /* The bytes come back in reverse order. */
551       for (; off < chunk; off++)
552         p[off] = lstr->unget_buffer[--lstr->unget_buffer_ind];
553       lstr->byte_count += chunk;
554       size -= chunk;
555     }
556
557   while (size > 0)
558     {
559       /* Take whatever we can from the in buffer */
560       chunk = min (size, lstr->in_buffer_current - lstr->in_buffer_ind);
561       if (chunk > 0)
562         {
563           memcpy (p + off, lstr->in_buffer + lstr->in_buffer_ind, chunk);
564           lstr->in_buffer_ind += chunk;
565           lstr->byte_count    += chunk;
566           size -= chunk;
567           off  += chunk;
568         }
569
570       /* If we need some more, try to get some more from the stream's end */
571       if (size > 0)
572         {
573           ssize_t retval = Lstream_read_more (lstr);
574           if (retval < 0)
575             error_occurred = 1;
576           if (retval <= 0)
577             break;
578         }
579     }
580
581   /* #### Beware of OFF ending up 0. */
582   if ((lstr->flags & LSTREAM_FL_NO_PARTIAL_CHARS) && off > 0)
583     {
584       /* It's quite possible for us to get passed an incomplete
585          character at the end.  We need to spit back that
586          incomplete character. */
587       const unsigned char *dataend = p + off - 1;
588       /* Optimize the most common case. */
589       if (!BYTE_ASCII_P (*dataend))
590         {
591           /* Go back to the beginning of the last (and possibly partial)
592              character, and bump forward to see if the character is
593              complete. */
594           VALIDATE_CHARPTR_BACKWARD (dataend);
595           if (dataend + REP_BYTES_BY_FIRST_BYTE (*dataend) != p + off)
596             {
597               size_t newoff = dataend - p;
598               /* If not, chop the size down to ignore the last char
599                  and stash it away for next time. */
600               Lstream_unread (lstr, dataend, off - newoff);
601               off = newoff;
602             }
603         }
604     }
605
606   return off == 0 && error_occurred ? -1 : (ssize_t) off;
607 }
608
609 void
610 Lstream_unread (Lstream *lstr, const void *data, size_t size)
611 {
612   const unsigned char *p = (const unsigned char *) data;
613
614   /* Make sure buffer is big enough */
615   DO_REALLOC (lstr->unget_buffer, lstr->unget_buffer_size,
616               lstr->unget_buffer_ind + size, unsigned char);
617
618   lstr->byte_count -= size;
619
620   /* Bytes have to go on in reverse order -- they are reversed
621      again when read back. */
622   while (size--)
623     lstr->unget_buffer[lstr->unget_buffer_ind++] = p[size];
624 }
625
626 int
627 Lstream_rewind (Lstream *lstr)
628 {
629   if (!lstr->imp->rewinder)
630     Lstream_internal_error ("lstream has no rewinder", lstr);
631   if (Lstream_flush (lstr) < 0)
632     return -1;
633   lstr->byte_count = 0;
634   return (lstr->imp->rewinder) (lstr);
635 }
636
637 int
638 Lstream_seekable_p (Lstream *lstr)
639 {
640   if (!lstr->imp->rewinder)
641     return 0;
642   if (!lstr->imp->seekable_p)
643     return 1;
644   return (lstr->imp->seekable_p) (lstr);
645 }
646
647 static int
648 Lstream_pseudo_close (Lstream *lstr)
649 {
650   if (!lstr->flags & LSTREAM_FL_IS_OPEN)
651     Lstream_internal_error ("lstream is not open", lstr);
652
653   /* don't check errors here -- best not to risk file descriptor loss */
654   return Lstream_flush (lstr);
655 }
656
657 int
658 Lstream_close (Lstream *lstr)
659 {
660   int rc = 0;
661
662   if (lstr->flags & LSTREAM_FL_IS_OPEN)
663     {
664       rc = Lstream_pseudo_close (lstr);
665       /*
666        * We used to return immediately if the closer method reported
667        * failure, leaving the stream open.  But this is no good, for
668        * the following reasons.
669        *
670        * 1. The finalizer method used in GC makes no provision for
671        *    failure, so we must not return without freeing buffer
672        *    memory.
673        *
674        * 2. The closer method may have already freed some memory
675        *    used for I/O in this stream.  E.g. encoding_closer frees
676        *    ENCODING_STREAM_DATA(stream)->runoff.  If a writer method
677        *    tries to use this buffer later, it will write into memory
678        *    that may have been allocated elsewhere.  Sometime later
679        *    you will see a sign that says "Welcome to Crash City."
680        *
681        * 3. The closer can report failure if a flush fails in the
682        *    other stream in a MULE encoding/decoding stream pair.
683        *    The other stream in the pair is closed, but returning
684        *    early leaves the current stream open.  If we try to
685        *    flush the current stream later, we will crash when the
686        *    flusher notices that the other end stream is closed.
687        *
688        * So, we no longer abort the close if the closer method
689        * reports some kind of failure.  We still report the failure
690        * to the caller.
691        */
692       if (lstr->imp->closer)
693         if ((lstr->imp->closer) (lstr) < 0)
694           rc = -1;
695     }
696
697   lstr->flags &= ~LSTREAM_FL_IS_OPEN;
698   lstr->byte_count = 0;
699   /* Note that Lstream_flush() reset all the buffer indices.  That way,
700      the next call to Lstream_putc(), Lstream_getc(), or Lstream_ungetc()
701      on a closed stream will call into the function equivalents, which will
702      cause an error. */
703
704   /* We set the pointers to 0 so that we don't lose when this function
705      is called more than once on the same object */
706   if (lstr->out_buffer)
707     {
708       xfree (lstr->out_buffer);
709       lstr->out_buffer = 0;
710     }
711   if (lstr->in_buffer)
712     {
713       xfree (lstr->in_buffer);
714       lstr->in_buffer = 0;
715     }
716   if (lstr->unget_buffer)
717     {
718       xfree (lstr->unget_buffer);
719       lstr->unget_buffer = 0;
720     }
721
722   return rc;
723 }
724
725 int
726 Lstream_fputc (Lstream *lstr, int c)
727 {
728   unsigned char ch = (unsigned char) c;
729   ssize_t retval = Lstream_write_1 (lstr, &ch, 1);
730   if (retval >= 0 && lstr->buffering == LSTREAM_LINE_BUFFERED && ch == '\n')
731     return Lstream_flush_out (lstr);
732   return retval < 0 ? -1 : 0;
733 }
734
735 int
736 Lstream_fgetc (Lstream *lstr)
737 {
738   unsigned char ch;
739   if (Lstream_read (lstr, &ch, 1) <= 0)
740     return -1;
741   return ch;
742 }
743
744 void
745 Lstream_fungetc (Lstream *lstr, int c)
746 {
747   unsigned char ch = (unsigned char) c;
748   Lstream_unread (lstr, &ch, 1);
749 }
750
751 \f
752 /************************ some stream implementations *********************/
753
754 /*********** a stdio stream ***********/
755
756 struct stdio_stream
757 {
758   FILE *file;
759   int closing;
760 };
761
762 #define STDIO_STREAM_DATA(stream) LSTREAM_TYPE_DATA (stream, stdio)
763
764 DEFINE_LSTREAM_IMPLEMENTATION ("stdio", lstream_stdio,
765                                sizeof (struct stdio_stream));
766
767 static Lisp_Object
768 make_stdio_stream_1 (FILE *stream, int flags, const char *mode)
769 {
770   Lisp_Object obj;
771   Lstream *lstr = Lstream_new (lstream_stdio, mode);
772   struct stdio_stream *str = STDIO_STREAM_DATA (lstr);
773   str->file = stream;
774   str->closing = flags & LSTR_CLOSING;
775   lstr->flags |= LSTREAM_FL_CLOSE_AT_DISKSAVE;
776   XSETLSTREAM (obj, lstr);
777   return obj;
778 }
779
780 Lisp_Object
781 make_stdio_input_stream (FILE *stream, int flags)
782 {
783   return make_stdio_stream_1 (stream, flags, "r");
784 }
785
786 Lisp_Object
787 make_stdio_output_stream (FILE *stream, int flags)
788 {
789   return make_stdio_stream_1 (stream, flags, "w");
790 }
791
792 /* #### From reading the Unix 98 specification, it appears that if we
793    want stdio_reader() to be completely correct, we should check for
794    0 < val < size and if so, check to see if an error has occurred.
795    If an error has occurred, but val is non-zero, we should go ahead
796    and act as if the read was successful, but remember in some fashion
797    or other, that an error has occurred, and report that on the next
798    call to stdio_reader instead of calling fread() again.
799
800    Currently, in such a case, we end up calling fread() twice and we
801    assume that
802
803    1) this is not harmful, and
804    2) the error will still be reported on the second read.
805
806    This is probably reasonable, so I don't think we should change this
807    code (it could even be argued that the error might have fixed
808    itself, so we should do the fread() again.  */
809
810 static ssize_t
811 stdio_reader (Lstream *stream, unsigned char *data, size_t size)
812 {
813   struct stdio_stream *str = STDIO_STREAM_DATA (stream);
814   size_t val = fread (data, 1, size, str->file);
815   if (!val && ferror (str->file))
816     return -1;
817   return val;
818 }
819
820 static ssize_t
821 stdio_writer (Lstream *stream, const unsigned char *data, size_t size)
822 {
823   struct stdio_stream *str = STDIO_STREAM_DATA (stream);
824   size_t val = fwrite (data, 1, size, str->file);
825   if (!val && ferror (str->file))
826     return -1;
827   return val;
828 }
829
830 static int
831 stdio_rewinder (Lstream *stream)
832 {
833   rewind (STDIO_STREAM_DATA (stream)->file);
834   return 0;
835 }
836
837 static int
838 stdio_seekable_p (Lstream *stream)
839 {
840   struct stat lestat;
841   struct stdio_stream *str = STDIO_STREAM_DATA (stream);
842
843   if (fstat (fileno (str->file), &lestat) < 0)
844     return 0;
845   return S_ISREG (lestat.st_mode);
846 }
847
848 static int
849 stdio_flusher (Lstream *stream)
850 {
851   struct stdio_stream *str = STDIO_STREAM_DATA (stream);
852   if (stream->flags & LSTREAM_FL_WRITE)
853     return fflush (str->file);
854   else
855     return 0;
856 }
857
858 static int
859 stdio_closer (Lstream *stream)
860 {
861   struct stdio_stream *str = STDIO_STREAM_DATA (stream);
862   if (str->closing)
863     return fclose (str->file);
864   else
865   if (stream->flags & LSTREAM_FL_WRITE)
866     return fflush (str->file);
867   else
868     return 0;
869 }
870
871 /*********** a file descriptor ***********/
872
873 struct filedesc_stream
874 {
875   int fd;
876   int pty_max_bytes;
877   Bufbyte eof_char;
878   int starting_pos;
879   int current_pos;
880   int end_pos;
881   int chars_sans_newline;
882   unsigned int closing :1;
883   unsigned int allow_quit :1;
884   unsigned int blocked_ok :1;
885   unsigned int pty_flushing :1;
886   unsigned int blocking_error_p :1;
887 };
888
889 #define FILEDESC_STREAM_DATA(stream) LSTREAM_TYPE_DATA (stream, filedesc)
890
891 DEFINE_LSTREAM_IMPLEMENTATION ("filedesc", lstream_filedesc,
892                                sizeof (struct filedesc_stream));
893
894 /* Make a stream that reads from or writes to a file descriptor FILEDESC.
895    OFFSET is the offset from the *current* file pointer that the reading
896    should start at.  COUNT is the number of bytes to be read (it is
897    ignored when writing); -1 for unlimited. */
898 static Lisp_Object
899 make_filedesc_stream_1 (int filedesc, int offset, int count, int flags,
900                         const char *mode)
901 {
902   Lisp_Object obj;
903   Lstream *lstr = Lstream_new (lstream_filedesc, mode);
904   struct filedesc_stream *fstr = FILEDESC_STREAM_DATA (lstr);
905   fstr->fd = filedesc;
906   fstr->closing      = !!(flags & LSTR_CLOSING);
907   fstr->allow_quit   = !!(flags & LSTR_ALLOW_QUIT);
908   fstr->blocked_ok   = !!(flags & LSTR_BLOCKED_OK);
909   fstr->pty_flushing = !!(flags & LSTR_PTY_FLUSHING);
910   fstr->blocking_error_p = 0;
911   fstr->chars_sans_newline = 0;
912   fstr->starting_pos = lseek (filedesc, offset, SEEK_CUR);
913   fstr->current_pos = max (fstr->starting_pos, 0);
914   if (count < 0)
915     fstr->end_pos = -1;
916   else
917     fstr->end_pos = fstr->starting_pos + count;
918   lstr->flags |= LSTREAM_FL_CLOSE_AT_DISKSAVE;
919   XSETLSTREAM (obj, lstr);
920   return obj;
921 }
922
923 Lisp_Object
924 make_filedesc_input_stream (int filedesc, int offset, int count, int flags)
925 {
926   return make_filedesc_stream_1 (filedesc, offset, count, flags, "r");
927 }
928
929 Lisp_Object
930 make_filedesc_output_stream (int filedesc, int offset, int count, int flags)
931 {
932   return make_filedesc_stream_1 (filedesc, offset, count, flags, "w");
933 }
934
935 static ssize_t
936 filedesc_reader (Lstream *stream, unsigned char *data, size_t size)
937 {
938   ssize_t nread;
939   struct filedesc_stream *str = FILEDESC_STREAM_DATA (stream);
940   if (str->end_pos >= 0)
941     size = min (size, (size_t) (str->end_pos - str->current_pos));
942   nread = str->allow_quit ?
943     read_allowing_quit (str->fd, data, size) :
944     read (str->fd, data, size);
945   if (nread > 0)
946     str->current_pos += nread;
947   return nread;
948 }
949
950 static int
951 errno_would_block_p (int val)
952 {
953 #ifdef EWOULDBLOCK
954   if (val == EWOULDBLOCK)
955     return 1;
956 #endif
957 #ifdef EAGAIN
958   if (val == EAGAIN)
959     return 1;
960 #endif
961   return 0;
962 }
963
964 static ssize_t
965 filedesc_writer (Lstream *stream, const unsigned char *data, size_t size)
966 {
967   struct filedesc_stream *str = FILEDESC_STREAM_DATA (stream);
968   ssize_t retval;
969   int need_newline = 0;
970
971   /* This function would be simple if it were not for the blasted
972      PTY max-bytes stuff.  Why the hell can't they just have written
973      the PTY drivers right so this problem doesn't exist?
974
975      Maybe all the PTY crap here should be moved into another stream
976      that does nothing but periodically insert EOF's as necessary. */
977   if (str->pty_flushing)
978     {
979       /* To make life easy, only send out one line at the most. */
980       const unsigned char *ptr;
981
982       ptr = (const unsigned char *) memchr (data, '\n', size);
983       if (ptr)
984         need_newline = 1;
985       else
986         ptr = data + size;
987       if (ptr - data >= str->pty_max_bytes - str->chars_sans_newline)
988         {
989           ptr = data + str->pty_max_bytes - str->chars_sans_newline;
990           need_newline = 0;
991         }
992       size = ptr - data;
993     }
994
995   /**** start of non-PTY-crap ****/
996   if (size > 0)
997     retval = str->allow_quit ?
998       write_allowing_quit (str->fd, data, size) :
999       write (str->fd, data, size);
1000   else
1001     retval = 0;
1002   if (retval < 0 && errno_would_block_p (errno) && str->blocked_ok)
1003     {
1004       str->blocking_error_p = 1;
1005       return 0;
1006     }
1007   str->blocking_error_p = 0;
1008   if (retval < 0)
1009     return retval;
1010   /**** end non-PTY-crap ****/
1011
1012   if (str->pty_flushing)
1013     {
1014       str->chars_sans_newline += retval;
1015       /* Note that a newline was not among the bytes written out.
1016          Add to the number of non-newline bytes written out,
1017          and flush with an EOF if necessary.  Be careful to
1018          keep track of write errors as we go along and look
1019          out for EWOULDBLOCK. */
1020       if (str->chars_sans_newline >= str->pty_max_bytes)
1021         {
1022           ssize_t retval2 = str->allow_quit ?
1023             write_allowing_quit (str->fd, &str->eof_char, 1) :
1024             write (str->fd, &str->eof_char, 1);
1025
1026           if (retval2 > 0)
1027             str->chars_sans_newline = 0;
1028           else if (retval2 < 0)
1029             {
1030               /* Error writing the EOF char.  If nothing got written,
1031                  then treat this as an error -- either return an error
1032                  condition or set the blocking-error flag. */
1033               if (retval == 0)
1034                 {
1035                   if (errno_would_block_p (errno) && str->blocked_ok)
1036                     {
1037                       str->blocking_error_p = 1;
1038                       return 0;
1039                     }
1040                   else
1041                     return retval2;
1042                 }
1043               else
1044                 return retval;
1045             }
1046         }
1047     }
1048
1049   /* The need_newline flag is necessary because otherwise when the
1050      first byte is a newline, we'd get stuck never writing anything
1051      in pty-flushing mode. */
1052   if (need_newline)
1053     {
1054       Bufbyte nl = '\n';
1055       ssize_t retval2 = str->allow_quit ?
1056         write_allowing_quit (str->fd, &nl, 1) :
1057         write (str->fd, &nl, 1);
1058
1059       if (retval2 > 0)
1060         {
1061           str->chars_sans_newline = 0;
1062           retval++;
1063         }
1064       else if (retval2 < 0)
1065         {
1066           /* Error writing the newline char.  If nothing got written,
1067              then treat this as an error -- either return an error
1068              condition or set the blocking-error flag. */
1069           if (retval == 0)
1070             {
1071               if (errno_would_block_p (errno) && str->blocked_ok)
1072                 {
1073                   str->blocking_error_p = 1;
1074                   return 0;
1075                 }
1076               else
1077                 return retval2;
1078             }
1079           else
1080             return retval;
1081         }
1082     }
1083
1084   return retval;
1085 }
1086
1087 static int
1088 filedesc_rewinder (Lstream *stream)
1089 {
1090   struct filedesc_stream *str = FILEDESC_STREAM_DATA (stream);
1091   if (str->starting_pos < 0 ||
1092       lseek (FILEDESC_STREAM_DATA (stream)->fd, str->starting_pos,
1093              SEEK_SET) == -1)
1094     return -1;
1095   else
1096     {
1097       str->current_pos = str->starting_pos;
1098       return 0;
1099     }
1100 }
1101
1102 static int
1103 filedesc_seekable_p (Lstream *stream)
1104 {
1105   struct filedesc_stream *str = FILEDESC_STREAM_DATA (stream);
1106   if (str->starting_pos < 0)
1107     return 0;
1108   else
1109     {
1110       struct stat lestat;
1111
1112       if (fstat (str->fd, &lestat) < 0)
1113         return 0;
1114       return S_ISREG (lestat.st_mode);
1115     }
1116 }
1117
1118 static int
1119 filedesc_closer (Lstream *stream)
1120 {
1121   struct filedesc_stream *str = FILEDESC_STREAM_DATA (stream);
1122   if (str->closing)
1123     return close (str->fd);
1124   else
1125     return 0;
1126 }
1127
1128 static int
1129 filedesc_was_blocked_p (Lstream *stream)
1130 {
1131   struct filedesc_stream *str = FILEDESC_STREAM_DATA (stream);
1132   return str->blocking_error_p;
1133 }
1134
1135 void
1136 filedesc_stream_set_pty_flushing (Lstream *stream, int pty_max_bytes,
1137                                   Bufbyte eof_char)
1138 {
1139   struct filedesc_stream *str = FILEDESC_STREAM_DATA (stream);
1140   str->pty_max_bytes = pty_max_bytes;
1141   str->eof_char = eof_char;
1142   str->pty_flushing = 1;
1143 }
1144
1145 int
1146 filedesc_stream_fd (Lstream *stream)
1147 {
1148   struct filedesc_stream *str = FILEDESC_STREAM_DATA (stream);
1149   return str->fd;
1150 }
1151
1152 /*********** read from a Lisp string ***********/
1153
1154 #define LISP_STRING_STREAM_DATA(stream) LSTREAM_TYPE_DATA (stream, lisp_string)
1155
1156 struct lisp_string_stream
1157 {
1158   Lisp_Object obj;
1159   Bytecount init_offset;
1160   Bytecount offset, end;
1161 };
1162
1163 DEFINE_LSTREAM_IMPLEMENTATION ("lisp-string", lstream_lisp_string,
1164                                sizeof (struct lisp_string_stream));
1165
1166 Lisp_Object
1167 make_lisp_string_input_stream (Lisp_Object string, Bytecount offset,
1168                                Bytecount len)
1169 {
1170   Lisp_Object obj;
1171   Lstream *lstr;
1172   struct lisp_string_stream *str;
1173
1174   CHECK_STRING (string);
1175   if (len < 0)
1176     len = XSTRING_LENGTH (string) - offset;
1177   assert (offset >= 0);
1178   assert (len >= 0);
1179   assert (offset + len <= XSTRING_LENGTH (string));
1180
1181   lstr = Lstream_new (lstream_lisp_string, "r");
1182   str = LISP_STRING_STREAM_DATA (lstr);
1183   str->offset = offset;
1184   str->end = offset + len;
1185   str->init_offset = offset;
1186   str->obj = string;
1187   XSETLSTREAM (obj, lstr);
1188   return obj;
1189 }
1190
1191 static ssize_t
1192 lisp_string_reader (Lstream *stream, unsigned char *data, size_t size)
1193 {
1194   struct lisp_string_stream *str = LISP_STRING_STREAM_DATA (stream);
1195   /* Don't lose if the string shrank past us ... */
1196   Bytecount offset = min (str->offset, XSTRING_LENGTH (str->obj));
1197   Bufbyte *strstart = XSTRING_DATA (str->obj);
1198   Bufbyte *start = strstart + offset;
1199
1200   /* ... or if someone changed the string and we ended up in the
1201      middle of a character. */
1202   /* Being in the middle of a character is `normal' unless
1203      LSTREAM_NO_PARTIAL_CHARS - mrb */
1204   if (stream->flags & LSTREAM_FL_NO_PARTIAL_CHARS)
1205     VALIDATE_CHARPTR_BACKWARD (start);
1206   offset = start - strstart;
1207   size = min (size, (size_t) (str->end - offset));
1208   memcpy (data, start, size);
1209   str->offset = offset + size;
1210   return size;
1211 }
1212
1213 static int
1214 lisp_string_rewinder (Lstream *stream)
1215 {
1216   struct lisp_string_stream *str = LISP_STRING_STREAM_DATA (stream);
1217   int pos = str->init_offset;
1218   if (pos > str->end)
1219     pos = str->end;
1220   /* Don't lose if the string shrank past us ... */
1221   pos = min (pos, XSTRING_LENGTH (str->obj));
1222   /* ... or if someone changed the string and we ended up in the
1223      middle of a character. */
1224   {
1225     Bufbyte *strstart = XSTRING_DATA (str->obj);
1226     Bufbyte *start = strstart + pos;
1227     VALIDATE_CHARPTR_BACKWARD (start);
1228     pos = start - strstart;
1229   }
1230   str->offset = pos;
1231   return 0;
1232 }
1233
1234 static Lisp_Object
1235 lisp_string_marker (Lisp_Object stream)
1236 {
1237   struct lisp_string_stream *str = LISP_STRING_STREAM_DATA (XLSTREAM (stream));
1238   return str->obj;
1239 }
1240
1241 /*********** a fixed buffer ***********/
1242
1243 #define FIXED_BUFFER_STREAM_DATA(stream) \
1244   LSTREAM_TYPE_DATA (stream, fixed_buffer)
1245
1246 struct fixed_buffer_stream
1247 {
1248   const unsigned char *inbuf;
1249   unsigned char *outbuf;
1250   size_t size;
1251   size_t offset;
1252 };
1253
1254 DEFINE_LSTREAM_IMPLEMENTATION ("fixed-buffer", lstream_fixed_buffer,
1255                                sizeof (struct fixed_buffer_stream));
1256
1257 Lisp_Object
1258 make_fixed_buffer_input_stream (const void *buf, size_t size)
1259 {
1260   Lisp_Object obj;
1261   Lstream *lstr = Lstream_new (lstream_fixed_buffer, "r");
1262   struct fixed_buffer_stream *str = FIXED_BUFFER_STREAM_DATA (lstr);
1263   str->inbuf = (const unsigned char *) buf;
1264   str->size = size;
1265   XSETLSTREAM (obj, lstr);
1266   return obj;
1267 }
1268
1269 Lisp_Object
1270 make_fixed_buffer_output_stream (void *buf, size_t size)
1271 {
1272   Lisp_Object obj;
1273   Lstream *lstr = Lstream_new (lstream_fixed_buffer, "w");
1274   struct fixed_buffer_stream *str = FIXED_BUFFER_STREAM_DATA (lstr);
1275   str->outbuf = (unsigned char *) buf;
1276   str->size = size;
1277   XSETLSTREAM (obj, lstr);
1278   return obj;
1279 }
1280
1281 static ssize_t
1282 fixed_buffer_reader (Lstream *stream, unsigned char *data, size_t size)
1283 {
1284   struct fixed_buffer_stream *str = FIXED_BUFFER_STREAM_DATA (stream);
1285   size = min (size, str->size - str->offset);
1286   memcpy (data, str->inbuf + str->offset, size);
1287   str->offset += size;
1288   return size;
1289 }
1290
1291 static ssize_t
1292 fixed_buffer_writer (Lstream *stream, const unsigned char *data, size_t size)
1293 {
1294   struct fixed_buffer_stream *str = FIXED_BUFFER_STREAM_DATA (stream);
1295   if (str->offset == str->size)
1296     {
1297       /* If we're at the end, just throw away the data and pretend
1298          we wrote all of it.  If we return 0, then the lstream routines
1299          will try again and again to write it out. */
1300       return size;
1301     }
1302   size = min (size, str->size - str->offset);
1303   memcpy (str->outbuf + str->offset, data, size);
1304   str->offset += size;
1305   return size;
1306 }
1307
1308 static int
1309 fixed_buffer_rewinder (Lstream *stream)
1310 {
1311   FIXED_BUFFER_STREAM_DATA (stream)->offset = 0;
1312   return 0;
1313 }
1314
1315 const unsigned char *
1316 fixed_buffer_input_stream_ptr (Lstream *stream)
1317 {
1318   assert (stream->imp == lstream_fixed_buffer);
1319   return FIXED_BUFFER_STREAM_DATA (stream)->inbuf;
1320 }
1321
1322 unsigned char *
1323 fixed_buffer_output_stream_ptr (Lstream *stream)
1324 {
1325   assert (stream->imp == lstream_fixed_buffer);
1326   return FIXED_BUFFER_STREAM_DATA (stream)->outbuf;
1327 }
1328
1329 /*********** write to a resizing buffer ***********/
1330
1331 #define RESIZING_BUFFER_STREAM_DATA(stream) \
1332   LSTREAM_TYPE_DATA (stream, resizing_buffer)
1333
1334 struct resizing_buffer_stream
1335 {
1336   unsigned char *buf;
1337   size_t allocked;
1338   int max_stored;
1339   int stored;
1340 };
1341
1342 DEFINE_LSTREAM_IMPLEMENTATION ("resizing-buffer", lstream_resizing_buffer,
1343                                sizeof (struct resizing_buffer_stream));
1344
1345 Lisp_Object
1346 make_resizing_buffer_output_stream (void)
1347 {
1348   Lisp_Object obj;
1349   XSETLSTREAM (obj, Lstream_new (lstream_resizing_buffer, "w"));
1350   return obj;
1351 }
1352
1353 static ssize_t
1354 resizing_buffer_writer (Lstream *stream, const unsigned char *data, size_t size)
1355 {
1356   struct resizing_buffer_stream *str = RESIZING_BUFFER_STREAM_DATA (stream);
1357   DO_REALLOC (str->buf, str->allocked, str->stored + size, unsigned char);
1358   memcpy (str->buf + str->stored, data, size);
1359   str->stored += size;
1360   str->max_stored = max (str->max_stored, str->stored);
1361   return size;
1362 }
1363
1364 static int
1365 resizing_buffer_rewinder (Lstream *stream)
1366 {
1367   RESIZING_BUFFER_STREAM_DATA (stream)->stored = 0;
1368   return 0;
1369 }
1370
1371 static int
1372 resizing_buffer_closer (Lstream *stream)
1373 {
1374   struct resizing_buffer_stream *str = RESIZING_BUFFER_STREAM_DATA (stream);
1375   if (str->buf)
1376     {
1377       xfree (str->buf);
1378       str->buf = 0;
1379     }
1380   return 0;
1381 }
1382
1383 unsigned char *
1384 resizing_buffer_stream_ptr (Lstream *stream)
1385 {
1386   return RESIZING_BUFFER_STREAM_DATA (stream)->buf;
1387 }
1388
1389 /*********** write to an unsigned-char dynarr ***********/
1390
1391 /* Note: If you have a dynarr whose type is not unsigned_char_dynarr
1392    but which is really just an unsigned_char_dynarr (e.g. its type
1393    is Bufbyte or Extbyte), just cast to unsigned_char_dynarr. */
1394
1395 #define DYNARR_STREAM_DATA(stream) \
1396   LSTREAM_TYPE_DATA (stream, dynarr)
1397
1398 struct dynarr_stream
1399 {
1400   unsigned_char_dynarr *dyn;
1401 };
1402
1403 DEFINE_LSTREAM_IMPLEMENTATION ("dynarr", lstream_dynarr,
1404                                sizeof (struct dynarr_stream));
1405
1406 Lisp_Object
1407 make_dynarr_output_stream (unsigned_char_dynarr *dyn)
1408 {
1409   Lisp_Object obj;
1410   XSETLSTREAM (obj, Lstream_new (lstream_dynarr, "w"));
1411   DYNARR_STREAM_DATA (XLSTREAM (obj))->dyn = dyn;
1412   return obj;
1413 }
1414
1415 static ssize_t
1416 dynarr_writer (Lstream *stream, const unsigned char *data, size_t size)
1417 {
1418   struct dynarr_stream *str = DYNARR_STREAM_DATA (stream);
1419   Dynarr_add_many (str->dyn, data, size);
1420   return size;
1421 }
1422
1423 static int
1424 dynarr_rewinder (Lstream *stream)
1425 {
1426   Dynarr_reset (DYNARR_STREAM_DATA (stream)->dyn);
1427   return 0;
1428 }
1429
1430 static int
1431 dynarr_closer (Lstream *stream)
1432 {
1433   return 0;
1434 }
1435
1436 /************ read from or write to a Lisp buffer ************/
1437
1438 /* Note: Lisp-buffer read streams never return partial characters,
1439    and Lisp-buffer write streams expect to never get partial
1440    characters. */
1441
1442 #define LISP_BUFFER_STREAM_DATA(stream) \
1443   LSTREAM_TYPE_DATA (stream, lisp_buffer)
1444
1445 struct lisp_buffer_stream
1446 {
1447   Lisp_Object buffer;
1448   Lisp_Object orig_start;
1449   /* we use markers to properly deal with insertion/deletion */
1450   Lisp_Object start, end;
1451   int flags;
1452 };
1453
1454 DEFINE_LSTREAM_IMPLEMENTATION ("lisp-buffer", lstream_lisp_buffer,
1455                                sizeof (struct lisp_buffer_stream));
1456
1457 static Lisp_Object
1458 make_lisp_buffer_stream_1 (struct buffer *buf, Bufpos start, Bufpos end,
1459                            int flags, const char *mode)
1460 {
1461   Lisp_Object obj;
1462   Lstream *lstr;
1463   struct lisp_buffer_stream *str;
1464   Bufpos bmin, bmax;
1465   int reading = !strcmp (mode, "r");
1466
1467   /* Make sure the luser didn't pass "w" in. */
1468   if (!strcmp (mode, "w"))
1469     abort ();
1470
1471   if (flags & LSTR_IGNORE_ACCESSIBLE)
1472     {
1473       bmin = BUF_BEG (buf);
1474       bmax = BUF_Z (buf);
1475     }
1476   else
1477     {
1478       bmin = BUF_BEGV (buf);
1479       bmax = BUF_ZV (buf);
1480     }
1481
1482   if (start == -1)
1483     start = bmin;
1484   if (end == -1)
1485     end = bmax;
1486   assert (bmin <= start);
1487   assert (start <= bmax);
1488   if (reading)
1489     {
1490       assert (bmin  <= end);
1491       assert (end   <= bmax);
1492       assert (start <= end);
1493     }
1494
1495   lstr = Lstream_new (lstream_lisp_buffer, mode);
1496   str = LISP_BUFFER_STREAM_DATA (lstr);
1497   {
1498     Lisp_Object marker;
1499     Lisp_Object buffer;
1500
1501     XSETBUFFER (buffer, buf);
1502     marker = Fmake_marker ();
1503     Fset_marker (marker, make_int (start), buffer);
1504     str->start = marker;
1505     marker = Fmake_marker ();
1506     Fset_marker (marker, make_int (start), buffer);
1507     str->orig_start = marker;
1508     if (reading)
1509       {
1510         marker = Fmake_marker ();
1511         Fset_marker (marker, make_int (end), buffer);
1512         str->end = marker;
1513       }
1514     else
1515       str->end = Qnil;
1516     str->buffer = buffer;
1517   }
1518   str->flags = flags;
1519   XSETLSTREAM (obj, lstr);
1520   return obj;
1521 }
1522
1523 Lisp_Object
1524 make_lisp_buffer_input_stream (struct buffer *buf, Bufpos start, Bufpos end,
1525                                int flags)
1526 {
1527   return make_lisp_buffer_stream_1 (buf, start, end, flags, "r");
1528 }
1529
1530 Lisp_Object
1531 make_lisp_buffer_output_stream (struct buffer *buf, Bufpos pos, int flags)
1532 {
1533   Lisp_Object lstr = make_lisp_buffer_stream_1 (buf, pos, 0, flags, "wc");
1534
1535   Lstream_set_character_mode (XLSTREAM (lstr));
1536   return lstr;
1537 }
1538
1539 static ssize_t
1540 lisp_buffer_reader (Lstream *stream, unsigned char *data, size_t size)
1541 {
1542   struct lisp_buffer_stream *str = LISP_BUFFER_STREAM_DATA (stream);
1543   unsigned char *orig_data = data;
1544   Bytind start;
1545   Bytind end;
1546   struct buffer *buf = XBUFFER (str->buffer);
1547
1548   if (!BUFFER_LIVE_P (buf))
1549     return 0; /* Fut. */
1550
1551   /* NOTE: We do all our operations in Bytind's.
1552      Keep in mind that SIZE is a value in bytes, not chars. */
1553
1554   start = bi_marker_position (str->start);
1555   end = bi_marker_position (str->end);
1556   if (!(str->flags & LSTR_IGNORE_ACCESSIBLE))
1557     {
1558       start = bytind_clip_to_bounds (BI_BUF_BEGV (buf), start,
1559                                      BI_BUF_ZV (buf));
1560       end = bytind_clip_to_bounds (BI_BUF_BEGV (buf), end,
1561                                    BI_BUF_ZV (buf));
1562     }
1563
1564   size = min (size, (size_t) (end - start));
1565   end = start + size;
1566   /* We cannot return a partial character. */
1567   VALIDATE_BYTIND_BACKWARD (buf, end);
1568
1569   while (start < end)
1570     {
1571       Bytind ceil;
1572       Bytecount chunk;
1573
1574       if (str->flags & LSTR_IGNORE_ACCESSIBLE)
1575         ceil = BI_BUF_CEILING_OF_IGNORE_ACCESSIBLE (buf, start);
1576       else
1577         ceil = BI_BUF_CEILING_OF (buf, start);
1578       chunk = min (ceil, end) - start;
1579       memcpy (data, BI_BUF_BYTE_ADDRESS (buf, start), chunk);
1580       data += chunk;
1581       start += chunk;
1582     }
1583
1584   if (EQ (buf->selective_display, Qt) && str->flags & LSTR_SELECTIVE)
1585     {
1586       /* What a kludge.  What a kludge.  What a kludge. */
1587       unsigned char *p;
1588       for (p = orig_data; p < data; p++)
1589         if (*p == '\r')
1590           *p = '\n';
1591     }
1592
1593   set_bi_marker_position (str->start, end);
1594   return data - orig_data;
1595 }
1596
1597 static ssize_t
1598 lisp_buffer_writer (Lstream *stream, const unsigned char *data, size_t size)
1599 {
1600   struct lisp_buffer_stream *str = LISP_BUFFER_STREAM_DATA (stream);
1601   Bufpos pos;
1602   struct buffer *buf = XBUFFER (str->buffer);
1603
1604   if (!BUFFER_LIVE_P (buf))
1605     return 0; /* Fut. */
1606
1607   pos = marker_position (str->start);
1608   pos += buffer_insert_raw_string_1 (buf, pos, data, size, 0);
1609   set_marker_position (str->start, pos);
1610   return size;
1611 }
1612
1613 static int
1614 lisp_buffer_rewinder (Lstream *stream)
1615 {
1616   struct lisp_buffer_stream *str =
1617     LISP_BUFFER_STREAM_DATA (stream);
1618   struct buffer *buf = XBUFFER (str->buffer);
1619   long pos = marker_position (str->orig_start);
1620   if (!BUFFER_LIVE_P (buf))
1621     return -1; /* Fut. */
1622   if (pos > BUF_ZV (buf))
1623     pos = BUF_ZV (buf);
1624   if (pos < marker_position (str->orig_start))
1625     pos = marker_position (str->orig_start);
1626   if (MARKERP (str->end) && pos > marker_position (str->end))
1627     pos = marker_position (str->end);
1628   set_marker_position (str->start, pos);
1629   return 0;
1630 }
1631
1632 static Lisp_Object
1633 lisp_buffer_marker (Lisp_Object stream)
1634 {
1635   struct lisp_buffer_stream *str =
1636     LISP_BUFFER_STREAM_DATA (XLSTREAM (stream));
1637
1638   mark_object (str->start);
1639   mark_object (str->end);
1640   return str->buffer;
1641 }
1642
1643 Bufpos
1644 lisp_buffer_stream_startpos (Lstream *stream)
1645 {
1646   return marker_position (LISP_BUFFER_STREAM_DATA (stream)->start);
1647 }
1648
1649 \f
1650 /************************************************************************/
1651 /*                            initialization                            */
1652 /************************************************************************/
1653
1654 void
1655 lstream_type_create (void)
1656 {
1657   LSTREAM_HAS_METHOD (stdio, reader);
1658   LSTREAM_HAS_METHOD (stdio, writer);
1659   LSTREAM_HAS_METHOD (stdio, rewinder);
1660   LSTREAM_HAS_METHOD (stdio, seekable_p);
1661   LSTREAM_HAS_METHOD (stdio, flusher);
1662   LSTREAM_HAS_METHOD (stdio, closer);
1663
1664   LSTREAM_HAS_METHOD (filedesc, reader);
1665   LSTREAM_HAS_METHOD (filedesc, writer);
1666   LSTREAM_HAS_METHOD (filedesc, was_blocked_p);
1667   LSTREAM_HAS_METHOD (filedesc, rewinder);
1668   LSTREAM_HAS_METHOD (filedesc, seekable_p);
1669   LSTREAM_HAS_METHOD (filedesc, closer);
1670
1671   LSTREAM_HAS_METHOD (lisp_string, reader);
1672   LSTREAM_HAS_METHOD (lisp_string, rewinder);
1673   LSTREAM_HAS_METHOD (lisp_string, marker);
1674
1675   LSTREAM_HAS_METHOD (fixed_buffer, reader);
1676   LSTREAM_HAS_METHOD (fixed_buffer, writer);
1677   LSTREAM_HAS_METHOD (fixed_buffer, rewinder);
1678
1679   LSTREAM_HAS_METHOD (resizing_buffer, writer);
1680   LSTREAM_HAS_METHOD (resizing_buffer, rewinder);
1681   LSTREAM_HAS_METHOD (resizing_buffer, closer);
1682
1683   LSTREAM_HAS_METHOD (dynarr, writer);
1684   LSTREAM_HAS_METHOD (dynarr, rewinder);
1685   LSTREAM_HAS_METHOD (dynarr, closer);
1686
1687   LSTREAM_HAS_METHOD (lisp_buffer, reader);
1688   LSTREAM_HAS_METHOD (lisp_buffer, writer);
1689   LSTREAM_HAS_METHOD (lisp_buffer, rewinder);
1690   LSTREAM_HAS_METHOD (lisp_buffer, marker);
1691 }
1692
1693 void
1694 reinit_vars_of_lstream (void)
1695 {
1696   int i;
1697
1698   for (i = 0; i < countof (Vlstream_free_list); i++)
1699     {
1700       Vlstream_free_list[i] = Qnil;
1701       staticpro_nodump (&Vlstream_free_list[i]);
1702     }
1703 }
1704
1705 void
1706 vars_of_lstream (void)
1707 {
1708   INIT_LRECORD_IMPLEMENTATION (lstream);
1709
1710   reinit_vars_of_lstream ();
1711 }