update from main archive 961214
[kopensolaris-gnu/glibc.git] / libio / genops.c
1 /*
2 Copyright (C) 1993, 1995 Free Software Foundation
3
4 This file is part of the GNU IO Library.  This library is free
5 software; you can redistribute it and/or modify it under the
6 terms of the GNU General Public License as published by the
7 Free Software Foundation; either version 2, or (at your option)
8 any later version.
9
10 This library is distributed in the hope that it will be useful,
11 but WITHOUT ANY WARRANTY; without even the implied warranty of
12 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
13 GNU General Public License for more details.
14
15 You should have received a copy of the GNU General Public License
16 along with this library; see the file COPYING.  If not, write to the Free
17 Software Foundation, 59 Temple Place - Suite 330, Boston, MA  02111-1307, USA.
18
19 As a special exception, if you link this library with files
20 compiled with a GNU compiler to produce an executable, this does not cause
21 the resulting executable to be covered by the GNU General Public License.
22 This exception does not however invalidate any other reasons why
23 the executable file might be covered by the GNU General Public License. */
24
25 /* Generic or default I/O operations. */
26
27 #include "libioP.h"
28 #ifdef __STDC__
29 #include <stdlib.h>
30 #endif
31 #include <string.h>
32
33 void
34 DEFUN(_IO_un_link, (fp),
35       _IO_FILE *fp)
36 {
37   if (fp->_flags & _IO_LINKED) {
38     _IO_FILE **f;
39     for (f = &_IO_list_all; *f != NULL; f = &(*f)->_chain) {
40       if (*f == fp) {
41         *f = fp->_chain;
42         break;
43       }
44     }
45     fp->_flags &= ~_IO_LINKED;
46   }
47 }
48
49 void
50 DEFUN(_IO_link_in, (fp),
51       _IO_FILE *fp)
52 {
53     if ((fp->_flags & _IO_LINKED) == 0) {
54         fp->_flags |= _IO_LINKED;
55         fp->_chain = _IO_list_all;
56         _IO_list_all = fp;
57     }
58 }
59
60 /* Return minimum _pos markers
61    Assumes the current get area is the main get area. */
62
63 _IO_size_t
64 DEFUN(_IO_least_marker, (fp),
65       register _IO_FILE *fp)
66 {
67   _IO_ssize_t least_so_far = fp->_IO_read_end - fp->_IO_read_base;
68   register struct _IO_marker *mark;
69   for (mark = fp->_markers; mark != NULL; mark = mark->_next)
70     if (mark->_pos < least_so_far)
71       least_so_far = mark->_pos;
72   return least_so_far;
73 }
74
75 /* Switch current get area from backup buffer to (start of) main get area. */
76
77 void
78 DEFUN(_IO_switch_to_main_get_area, (fp),
79       _IO_FILE *fp)
80 {
81   char *tmp;
82   fp->_flags &= ~_IO_IN_BACKUP;
83   /* Swap _IO_read_end and _IO_save_end. */
84   tmp = fp->_IO_read_end; fp->_IO_read_end= fp->_IO_save_end; fp->_IO_save_end= tmp;
85   /* Swap _IO_read_base and _IO_save_base. */
86   tmp = fp->_IO_read_base; fp->_IO_read_base = fp->_IO_save_base; fp->_IO_save_base = tmp;
87   fp->_IO_read_ptr = fp->_IO_read_base;
88 }
89
90 /* Switch current get area from main get area to (end of) backup area. */
91
92 void
93 DEFUN(_IO_switch_to_backup_area, (fp),
94      register _IO_FILE *fp)
95 {
96   char *tmp;
97   fp->_flags |= _IO_IN_BACKUP;
98   /* Swap _IO_read_end and _IO_save_end. */
99   tmp = fp->_IO_read_end; fp->_IO_read_end = fp->_IO_save_end; fp->_IO_save_end = tmp;
100   /* Swap _gbase and _IO_save_base. */
101   tmp = fp->_IO_read_base; fp->_IO_read_base = fp->_IO_save_base; fp->_IO_save_base = tmp;
102   fp->_IO_read_ptr = fp->_IO_read_end;
103 }
104
105 int
106 DEFUN(_IO_switch_to_get_mode, (fp),
107      register _IO_FILE *fp)
108 {
109   if (fp->_IO_write_ptr > fp->_IO_write_base)
110     if (_IO_OVERFLOW (fp, EOF) == EOF)
111       return EOF;
112   if (_IO_in_backup(fp))
113     fp->_IO_read_base = fp->_IO_backup_base;
114   else
115     {
116       fp->_IO_read_base = fp->_IO_buf_base;
117       if (fp->_IO_write_ptr > fp->_IO_read_end)
118         fp->_IO_read_end = fp->_IO_write_ptr;
119     }
120   fp->_IO_read_ptr = fp->_IO_write_ptr;
121
122   fp->_IO_write_base = fp->_IO_write_ptr = fp->_IO_write_end = fp->_IO_read_ptr;
123
124   fp->_flags &= ~_IO_CURRENTLY_PUTTING;
125   return 0;
126 }
127
128 void
129 DEFUN(_IO_free_backup_area, (fp),
130      register _IO_FILE *fp)
131 {
132   if (_IO_in_backup (fp))
133     _IO_switch_to_main_get_area(fp);  /* Just in case. */
134   free (fp->_IO_save_base);
135   fp->_IO_save_base = NULL;
136   fp->_IO_save_end = NULL;
137   fp->_IO_backup_base = NULL;
138 }
139
140 #if 0
141 int
142 DEFUN(_IO_switch_to_put_mode, (fp),
143       register _IO_FILE *fp)
144 {
145   fp->_IO_write_base = fp->_IO_read_ptr;
146   fp->_IO_write_ptr = fp->_IO_read_ptr;
147   /* Following is wrong if line- or un-buffered? */
148   fp->_IO_write_end = fp->_flags & _IO_IN_BACKUP ? fp->_IO_read_end : fp->_IO_buf_end;
149
150   fp->_IO_read_ptr = fp->_IO_read_end;
151   fp->_IO_read_base = fp->_IO_read_end;
152
153   fp->_flags |= _IO_CURRENTLY_PUTTING;
154   return 0;
155 }
156 #endif
157
158 int
159 DEFUN(__overflow, (f, ch),
160       _IO_FILE *f AND int ch)
161 {
162   return _IO_OVERFLOW (f, ch);
163 }
164
165 static int
166 DEFUN(save_for_backup, (fp),
167       _IO_FILE *fp)
168 {
169   /* Append [_IO_read_base.._IO_read_end] to backup area. */
170   int least_mark = _IO_least_marker(fp);
171   /* needed_size is how much space we need in the backup area. */
172   int needed_size = (fp->_IO_read_end - fp->_IO_read_base) - least_mark;
173   int current_Bsize = fp->_IO_save_end - fp->_IO_save_base;
174   int avail; /* Extra space available for future expansion. */
175   int delta;
176   struct _IO_marker *mark;
177   if (needed_size > current_Bsize)
178     {
179       char *new_buffer;
180       avail = 100;
181       new_buffer = (char*)malloc(avail+needed_size);
182       if (new_buffer == NULL)
183         return EOF;             /* FIXME */
184       if (least_mark < 0)
185         {
186           memcpy(new_buffer + avail,
187                  fp->_IO_save_end + least_mark,
188                  -least_mark);
189           memcpy(new_buffer +avail - least_mark,
190                  fp->_IO_read_base,
191                  fp->_IO_read_end - fp->_IO_read_base);
192         }
193       else
194         memcpy(new_buffer + avail,
195                fp->_IO_read_base + least_mark,
196                needed_size);
197       if (fp->_IO_save_base)
198         free (fp->_IO_save_base);
199       fp->_IO_save_base = new_buffer;
200       fp->_IO_save_end = new_buffer + avail + needed_size;
201     }
202   else
203     {
204       avail = current_Bsize - needed_size;
205       if (least_mark < 0)
206         {
207           memmove(fp->_IO_save_base + avail,
208                   fp->_IO_save_end + least_mark,
209                   -least_mark);
210           memcpy(fp->_IO_save_base + avail - least_mark,
211                  fp->_IO_read_base,
212                  fp->_IO_read_end - fp->_IO_read_base);
213         }
214       else if (needed_size > 0)
215         memcpy(fp->_IO_save_base + avail,
216                fp->_IO_read_base + least_mark,
217                needed_size);
218     }
219   /* FIXME: Dubious arithmetic if pointers are NULL */
220   fp->_IO_backup_base = fp->_IO_save_base + avail;
221   /* Adjust all the streammarkers. */
222   delta = fp->_IO_read_end - fp->_IO_read_base;
223   for (mark = fp->_markers; mark != NULL; mark = mark->_next)
224     mark->_pos -= delta;
225   return 0;
226 }
227
228 int
229 DEFUN(__underflow, (fp),
230       _IO_FILE *fp)
231 {
232   if (_IO_in_put_mode(fp))
233     if (_IO_switch_to_get_mode(fp) == EOF) return EOF;
234   if (fp->_IO_read_ptr < fp->_IO_read_end)
235     return *(unsigned char*)fp->_IO_read_ptr;
236   if (_IO_in_backup(fp))
237     {
238       _IO_switch_to_main_get_area(fp);
239       if (fp->_IO_read_ptr < fp->_IO_read_end)
240         return *fp->_IO_read_ptr;
241     }
242   if (_IO_have_markers(fp))
243     {
244       if (save_for_backup (fp))
245         return EOF;
246     }
247   else if (_IO_have_backup(fp))
248     _IO_free_backup_area(fp);
249   return _IO_UNDERFLOW (fp);
250 }
251
252 int
253 DEFUN(__uflow, (fp),
254      _IO_FILE *fp)
255 {
256   if (_IO_in_put_mode(fp))
257     if (_IO_switch_to_get_mode(fp) == EOF) return EOF;
258   if (fp->_IO_read_ptr < fp->_IO_read_end)
259     return *(unsigned char*)fp->_IO_read_ptr++;
260   if (_IO_in_backup(fp))
261     {
262       _IO_switch_to_main_get_area(fp);
263       if (fp->_IO_read_ptr < fp->_IO_read_end)
264         return *fp->_IO_read_ptr++;
265     }
266   if (_IO_have_markers(fp))
267     {
268       if (save_for_backup (fp))
269         return EOF;
270     }
271   else if (_IO_have_backup(fp))
272     _IO_free_backup_area(fp);
273   return _IO_UFLOW (fp);
274 }
275
276 void
277 DEFUN(_IO_setb, (f, b, eb, a),
278       _IO_FILE *f AND char *b AND char *eb AND int a)
279 {
280   if (f->_IO_buf_base && !(f->_flags & _IO_USER_BUF))
281     FREE_BUF(f->_IO_buf_base, _IO_blen (f));
282   f->_IO_buf_base = b;
283   f->_IO_buf_end = eb;
284   if (a)
285     f->_flags &= ~_IO_USER_BUF;
286   else
287     f->_flags |= _IO_USER_BUF;
288 }
289
290 void
291 DEFUN(_IO_doallocbuf, (fp),
292       register _IO_FILE *fp)
293 {
294   if (fp->_IO_buf_base)
295     return;
296   if (!(fp->_flags & _IO_UNBUFFERED))
297     if (_IO_DOALLOCATE (fp) != EOF)
298       return;
299   _IO_setb(fp, fp->_shortbuf, fp->_shortbuf+1, 0);
300 }
301
302 int
303 DEFUN(_IO_default_underflow, (fp),
304       _IO_FILE *fp)
305 {
306   return EOF;
307 }
308
309 int
310 DEFUN(_IO_default_uflow, (fp),
311       _IO_FILE *fp)
312 {
313   int ch = _IO_UNDERFLOW (fp);
314   if (ch == EOF)
315     return EOF;
316   return *(unsigned char*)fp->_IO_read_ptr++;
317 }
318
319 _IO_size_t
320 DEFUN(_IO_default_xsputn, (f, data, n),
321       register _IO_FILE *f AND const void *data AND _IO_size_t n)
322 {
323   register const char *s = (char*) data;
324   register _IO_size_t more = n;
325   if (more <= 0)
326     return 0;
327   for (;;)
328     {
329       _IO_ssize_t count = f->_IO_write_end - f->_IO_write_ptr; /* Space available. */
330       if (count > 0)
331         {
332           if ((_IO_size_t) count > more)
333             count = more;
334           if (count > 20)
335             {
336               memcpy(f->_IO_write_ptr, s, count);
337               s += count;
338               f->_IO_write_ptr += count;
339             }
340           else if (count <= 0)
341             count = 0;
342           else
343             {
344               register char *p = f->_IO_write_ptr;
345               register _IO_ssize_t i;
346               for (i = count; --i >= 0; ) *p++ = *s++;
347               f->_IO_write_ptr = p;
348             }
349           more -= count;
350         }
351       if (more == 0 || __overflow(f, (unsigned char)*s++) == EOF)
352         break;
353       more--;
354     }
355   return n - more;
356 }
357
358 _IO_size_t
359 DEFUN(_IO_sgetn, (fp, data, n),
360       _IO_FILE *fp AND void *data AND _IO_size_t n)
361 {
362   /* FIXME handle putback buffer here! */
363   return _IO_XSGETN (fp, data, n);
364 }
365
366 _IO_size_t
367 DEFUN(_IO_default_xsgetn, (fp, data, n),
368       _IO_FILE *fp AND void *data AND _IO_size_t n)
369 {
370   register _IO_size_t more = n;
371   register char *s = (char*) data;
372   for (;;)
373     {
374       _IO_ssize_t count = fp->_IO_read_end - fp->_IO_read_ptr; /* Data available. */
375       if (count > 0)
376         {
377           if ((_IO_size_t) count > more)
378             count = more;
379           if (count > 20)
380             {
381               memcpy(s, fp->_IO_read_ptr, count);
382               s += count;
383               fp->_IO_read_ptr += count;
384             }
385           else if (count <= 0)
386             count = 0;
387           else
388             {
389               register char *p = fp->_IO_read_ptr;
390               register int i = (int)count;
391               while (--i >= 0) *s++ = *p++;
392               fp->_IO_read_ptr = p;
393             }
394             more -= count;
395         }
396       if (more == 0 || __underflow(fp) == EOF)
397         break;
398     }
399   return n - more;
400 }
401
402 int
403 DEFUN(_IO_sync, (fp),
404       register _IO_FILE *fp)
405 {
406   return 0;
407 }
408
409 _IO_FILE*
410 DEFUN(_IO_default_setbuf, (fp, p, len),
411       register _IO_FILE *fp AND char* p AND _IO_ssize_t len)
412 {
413     if (_IO_SYNC (fp) == EOF)
414         return NULL;
415     if (p == NULL || len == 0)
416       {
417         fp->_flags |= _IO_UNBUFFERED;
418         _IO_setb(fp, fp->_shortbuf, fp->_shortbuf+1, 0);
419       }
420     else
421       {
422         fp->_flags &= ~_IO_UNBUFFERED;
423         _IO_setb(fp, p, p+len, 0);
424       }
425     fp->_IO_write_base = fp->_IO_write_ptr = fp->_IO_write_end = 0;
426     fp->_IO_read_base = fp->_IO_read_ptr = fp->_IO_read_end = 0;
427     return fp;
428 }
429
430 _IO_pos_t
431 DEFUN(_IO_default_seekpos, (fp, pos, mode),
432       _IO_FILE *fp AND _IO_pos_t pos AND int mode)
433 {
434   return _IO_SEEKOFF (fp, _IO_pos_as_off(pos), 0, mode);
435 }
436
437 int
438 DEFUN(_IO_default_doallocate, (fp),
439       _IO_FILE *fp)
440 {
441   char *buf;
442
443   ALLOC_BUF(buf, _IO_BUFSIZ, EOF);
444   _IO_setb(fp, buf, buf+_IO_BUFSIZ, 1);
445   return 1;
446 }
447
448 void
449 DEFUN(_IO_init, (fp, flags),
450       register _IO_FILE *fp AND int flags)
451 {
452   fp->_flags = _IO_MAGIC|flags;
453   fp->_IO_buf_base = NULL;
454   fp->_IO_buf_end = NULL;
455   fp->_IO_read_base = NULL;
456   fp->_IO_read_ptr = NULL;
457   fp->_IO_read_end = NULL;
458   fp->_IO_write_base = NULL;
459   fp->_IO_write_ptr = NULL;
460   fp->_IO_write_end = NULL;
461   fp->_chain = NULL; /* Not necessary. */
462
463   fp->_IO_save_base = NULL;
464   fp->_IO_backup_base = NULL;
465   fp->_IO_save_end = NULL;
466   fp->_markers = NULL;
467   fp->_cur_column = 0;
468 #ifdef _IO_MTSAFE_IO
469   _IO_lock_init_recursive (*fp->_lock);
470 #endif
471 }
472
473 int
474 DEFUN(_IO_default_sync, (fp),
475       _IO_FILE *fp)
476 {
477   return 0;
478 }
479
480 /* The way the C++ classes are mapped into the C functions in the
481    current implementation, this function can get called twice! */
482
483 void
484 DEFUN(_IO_default_finish, (fp),
485       _IO_FILE *fp)
486 {
487   struct _IO_marker *mark;
488   if (fp->_IO_buf_base && !(fp->_flags & _IO_USER_BUF))
489     {
490       FREE_BUF(fp->_IO_buf_base, _IO_blen (fp));
491       fp->_IO_buf_base = fp->_IO_buf_end = NULL;
492     }
493
494   for (mark = fp->_markers; mark != NULL; mark = mark->_next)
495     mark->_sbuf = NULL;
496
497   if (fp->_IO_save_base)
498     {
499       free (fp->_IO_save_base);
500       fp->_IO_save_base = NULL;
501     }
502
503 #ifdef _IO_MTSAFE_IO
504   _IO_lock_fini (*fp->_lock);
505 #endif
506
507   _IO_un_link(fp);
508 }
509
510 _IO_pos_t
511 DEFUN(_IO_default_seekoff, (fp, offset, dir, mode),
512       register _IO_FILE *fp AND _IO_off_t offset AND int dir AND int mode)
513 {
514     return _IO_pos_BAD;
515 }
516
517 int
518 DEFUN(_IO_sputbackc, (fp, c),
519       register _IO_FILE *fp AND int c)
520 {
521   int result;
522
523   if (fp->_IO_read_ptr > fp->_IO_read_base
524       && (unsigned char)fp->_IO_read_ptr[-1] == (unsigned char)c)
525     {
526       fp->_IO_read_ptr--;
527       result = (unsigned char)c;
528     }
529   else
530     result = _IO_PBACKFAIL (fp, c);
531
532   if (result != EOF)
533     fp->_flags &= ~_IO_EOF_SEEN;
534
535   return result;
536 }
537
538 int
539 DEFUN(_IO_sungetc, (fp),
540       register _IO_FILE *fp)
541 {
542   int result;
543
544   if (fp->_IO_read_ptr > fp->_IO_read_base)
545     {
546       fp->_IO_read_ptr--;
547       result = (unsigned char)*fp->_IO_read_ptr;
548     }
549   else
550     result = _IO_PBACKFAIL (fp, EOF);
551
552   if (result != EOF)
553     fp->_flags &= ~_IO_EOF_SEEN;
554
555   return result;
556 }
557
558 #if 0 /* Work in progress */
559 void
560 DEFUN(_IO_set_column, (fp, c),
561       register _IO_FILE *fp AND int c)
562 {
563   if (c == -1)
564     fp->_column = -1;
565   else
566     fp->_column = c - (fp->_IO_write_ptr - fp->_IO_write_base);
567 }
568 #else
569 int
570 DEFUN(_IO_set_column, (fp, i),
571       register _IO_FILE *fp AND int i)
572 {
573   fp->_cur_column = i+1;
574   return 0;
575 }
576 #endif
577
578
579 unsigned
580 DEFUN(_IO_adjust_column, (start, line, count),
581       unsigned start AND const char *line AND int count)
582 {
583   register const char *ptr = line + count;
584   while (ptr > line)
585     if (*--ptr == '\n')
586       return line + count - ptr - 1;
587   return start + count;
588 }
589
590 int
591 DEFUN(_IO_get_column, (fp),
592       register _IO_FILE *fp)
593 {
594   if (fp->_cur_column)
595     return _IO_adjust_column(fp->_cur_column - 1,
596                               fp->_IO_write_base,
597                               fp->_IO_write_ptr - fp->_IO_write_base);
598   return -1;
599 }
600
601 int
602 DEFUN_VOID(_IO_flush_all)
603 {
604   int result = 0;
605   _IO_FILE *fp;
606   for (fp = _IO_list_all; fp != NULL; fp = fp->_chain)
607     if (fp->_IO_write_ptr > fp->_IO_write_base
608         && _IO_OVERFLOW (fp, EOF) == EOF)
609       result = EOF;
610   return result;
611 }
612
613 void
614 DEFUN_VOID(_IO_flush_all_linebuffered)
615 {
616   _IO_FILE *fp;
617   for (fp = _IO_list_all; fp != NULL; fp = fp->_chain)
618     if (fp->_flags & _IO_LINE_BUF)
619       _IO_OVERFLOW (fp, EOF);
620 }
621
622 void
623 DEFUN_VOID(_IO_unbuffer_all)
624 {
625   _IO_FILE *fp;
626   for (fp = _IO_list_all; fp != NULL; fp = fp->_chain)
627     if (! (fp->_flags & _IO_UNBUFFERED))
628       _IO_SETBUF (fp, NULL, 0);
629 }
630
631 void
632 DEFUN_VOID(_IO_cleanup)
633 {
634   _IO_flush_all ();
635
636   /* We currently don't have a reliable mechanism for making sure that
637      C++ static destructors are executed in the correct order.
638      So it is possible that other static destructord might want to
639      write to cout - and they're supposed to be able to do so.
640
641      The following will make the standard streambufs be unbuffered,
642      which forces any output from late destructors to be written out. */
643   _IO_unbuffer_all ();
644 }
645
646 void
647 DEFUN(_IO_init_marker, (marker, fp),
648       struct _IO_marker *marker AND _IO_FILE *fp)
649 {
650   marker->_sbuf = fp;
651   if (_IO_in_put_mode(fp))
652     _IO_switch_to_get_mode(fp);
653   if (_IO_in_backup(fp))
654     marker->_pos = fp->_IO_read_ptr - fp->_IO_read_end;
655   else
656     marker->_pos = fp->_IO_read_ptr - fp->_IO_read_base;
657
658   /* Should perhaps sort the chain? */
659   marker->_next = fp->_markers;
660   fp->_markers = marker;
661 }
662
663 void
664 DEFUN(_IO_remove_marker, (marker),
665       register struct _IO_marker *marker)
666 {
667   /* Unlink from sb's chain. */
668   register struct _IO_marker **ptr = &marker->_sbuf->_markers;
669   for (; ; ptr = &(*ptr)->_next)
670     {
671       if (*ptr == NULL)
672         break;
673       else if (*ptr == marker)
674         {
675           *ptr = marker->_next;
676           return;
677         }
678     }
679 #if 0
680     if _sbuf has a backup area that is no longer needed, should we delete
681     it now, or wait until the next underflow?
682 #endif
683 }
684
685 #define BAD_DELTA EOF
686
687 int
688 DEFUN(_IO_marker_difference, (mark1, mark2),
689       struct _IO_marker *mark1 AND struct _IO_marker *mark2)
690 {
691   return mark1->_pos - mark2->_pos;
692 }
693
694 /* Return difference between MARK and current posistion of MARK's stream. */
695 int
696 DEFUN(_IO_marker_delta, (mark),
697       struct _IO_marker *mark)
698 {
699   int cur_pos;
700   if (mark->_sbuf == NULL)
701     return BAD_DELTA;
702   if (_IO_in_backup(mark->_sbuf))
703     cur_pos = mark->_sbuf->_IO_read_ptr - mark->_sbuf->_IO_read_end;
704   else
705     cur_pos = mark->_sbuf->_IO_read_ptr - mark->_sbuf->_IO_read_base;
706   return mark->_pos - cur_pos;
707 }
708
709 int
710 DEFUN(_IO_seekmark, (fp, mark, delta),
711       _IO_FILE *fp AND struct _IO_marker *mark AND int delta)
712 {
713   if (mark->_sbuf != fp)
714     return EOF;
715  if (mark->_pos >= 0)
716     {
717       if (_IO_in_backup(fp))
718         _IO_switch_to_main_get_area(fp);
719       fp->_IO_read_ptr = fp->_IO_read_base + mark->_pos;
720     }
721   else
722     {
723       if (!_IO_in_backup(fp))
724         _IO_switch_to_backup_area(fp);
725       fp->_IO_read_ptr = fp->_IO_read_end + mark->_pos;
726     }
727   return 0;
728 }
729
730 void
731 DEFUN(_IO_unsave_markers, (fp),
732      register _IO_FILE *fp)
733 {
734   register struct _IO_marker *mark = fp->_markers;
735   if (mark)
736     {
737 #ifdef TODO
738       streampos offset = seekoff(0, ios::cur, ios::in);
739       if (offset != EOF)
740         {
741           offset += eGptr() - Gbase();
742           for ( ; mark != NULL; mark = mark->_next)
743             mark->set_streampos(mark->_pos + offset);
744         }
745     else
746       {
747         for ( ; mark != NULL; mark = mark->_next)
748           mark->set_streampos(EOF);
749       }
750 #endif
751       fp->_markers = 0;
752     }
753
754   if (_IO_have_backup(fp))
755     _IO_free_backup_area(fp);
756 }
757
758 int
759 DEFUN(_IO_nobackup_pbackfail, (fp, c),
760      register _IO_FILE *fp AND int c)
761 {
762   if (fp->_IO_read_ptr > fp->_IO_read_base)
763         fp->_IO_read_ptr--;
764   if (c != EOF && *fp->_IO_read_ptr != c)
765       *fp->_IO_read_ptr = c;
766   return (unsigned char)c;
767 }
768
769 int
770 DEFUN(_IO_default_pbackfail, (fp, c),
771       register _IO_FILE *fp AND int c)
772 {
773   if (fp->_IO_read_ptr <= fp->_IO_read_base)
774       {
775         /* Need to handle a filebuf in write mode (switch to read mode). FIXME!*/
776         if (_IO_have_backup(fp) && !_IO_in_backup(fp))
777           _IO_switch_to_backup_area(fp);
778
779         if (!_IO_have_backup(fp))
780           {
781             /* No backup buffer: allocate one. */
782             /* Use nshort buffer, if unused? (probably not)  FIXME */
783             int backup_size = 128;
784             char *bbuf = (char*)malloc(backup_size);
785             if (bbuf == NULL)
786               return EOF;
787             fp->_IO_save_base = bbuf;
788             fp->_IO_save_end = fp->_IO_save_base + backup_size;
789             fp->_IO_backup_base = fp->_IO_save_end;
790             _IO_switch_to_backup_area(fp);
791           }
792         else if (fp->_IO_read_ptr <= fp->_IO_read_base)
793           {
794             /* Increase size of existing backup buffer. */
795             _IO_size_t new_size;
796             _IO_size_t old_size = fp->_IO_read_end - fp->_IO_read_base;
797             char *new_buf;
798             new_size = 2 * old_size;
799             new_buf = (char*)malloc(new_size);
800             if (new_buf == NULL)
801               return EOF;
802             memcpy(new_buf+(new_size-old_size), fp->_IO_read_base, old_size);
803             free (fp->_IO_read_base);
804             _IO_setg(fp,
805                      new_buf, new_buf+(new_size-old_size), new_buf+new_size);
806             fp->_IO_backup_base = fp->_IO_read_ptr;
807           }
808       }
809   fp->_IO_read_ptr--;
810   if (c != EOF && *fp->_IO_read_ptr != c)
811     *fp->_IO_read_ptr = c;
812   return (unsigned char)*fp->_IO_read_ptr;
813 }
814
815 _IO_pos_t
816 DEFUN(_IO_default_seek, (fp, offset, dir),
817       _IO_FILE *fp AND _IO_off_t offset AND int dir)
818 {
819   return _IO_pos_BAD;
820 }
821
822 int
823 DEFUN(_IO_default_stat, (fp, st),
824       _IO_FILE *fp AND void* st)
825 {
826   return EOF;
827 }
828
829 _IO_ssize_t
830 DEFUN(_IO_default_read, (fp, data, n),
831       register _IO_FILE* fp AND void* data AND _IO_ssize_t n)
832 {
833   return -1;
834 }
835
836 _IO_ssize_t
837 DEFUN(_IO_default_write, (fp, data, n),
838       register _IO_FILE* fp AND const void* data AND _IO_ssize_t n)
839 {
840   return 0;
841 }
842
843
844 #ifdef TODO
845 #if defined(linux)
846 #define IO_CLEANUP ;
847 #endif
848
849 #ifdef IO_CLEANUP
850   IO_CLEANUP
851 #else
852 struct __io_defs {
853     __io_defs() { }
854     ~__io_defs() { _IO_cleanup(); }
855 };
856 __io_defs io_defs__;
857 #endif
858
859 #endif /* TODO */
860
861 #ifdef weak_alias
862 weak_alias (_IO_cleanup, _cleanup)
863 #endif
864
865 #ifdef text_set_element
866 text_set_element(__libc_atexit, _cleanup);
867 #endif