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