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