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