comparison src/lstream.c @ 0:376386a54a3c r19-14

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