Back to index

glibc  2.9
genops.c
Go to the documentation of this file.
00001 /* Copyright (C) 1993,1995,1997-2002, 2003, 2004, 2006, 2007
00002    Free Software Foundation, Inc.
00003    This file is part of the GNU C Library.
00004 
00005    The GNU C Library is free software; you can redistribute it and/or
00006    modify it under the terms of the GNU Lesser General Public
00007    License as published by the Free Software Foundation; either
00008    version 2.1 of the License, or (at your option) any later version.
00009 
00010    The GNU C Library is distributed in the hope that it will be useful,
00011    but WITHOUT ANY WARRANTY; without even the implied warranty of
00012    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
00013    Lesser General Public License for more details.
00014 
00015    You should have received a copy of the GNU Lesser General Public
00016    License along with the GNU C Library; if not, write to the Free
00017    Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA
00018    02111-1307 USA.
00019 
00020    As a special exception, if you link the code in this file with
00021    files compiled with a GNU compiler to produce an executable,
00022    that does not cause the resulting executable to be covered by
00023    the GNU Lesser General Public License.  This exception does not
00024    however invalidate any other reasons why the executable file
00025    might be covered by the GNU Lesser General Public License.
00026    This exception applies to code released by its copyright holders
00027    in files containing the exception.  */
00028 
00029 /* Generic or default I/O operations. */
00030 
00031 #include "libioP.h"
00032 #ifdef __STDC__
00033 #include <stdlib.h>
00034 #endif
00035 #include <string.h>
00036 #include <stdbool.h>
00037 #ifdef _LIBC
00038 #include <sched.h>
00039 #endif
00040 
00041 #ifdef _IO_MTSAFE_IO
00042 static _IO_lock_t list_all_lock = _IO_lock_initializer;
00043 #endif
00044 
00045 /* Used to signal modifications to the list of FILE decriptors.  */
00046 static int _IO_list_all_stamp;
00047 
00048 
00049 static _IO_FILE *run_fp;
00050 
00051 static void
00052 flush_cleanup (void *not_used)
00053 {
00054   if (run_fp != NULL)
00055     _IO_funlockfile (run_fp);
00056 #ifdef _IO_MTSAFE_IO
00057   _IO_lock_unlock (list_all_lock);
00058 #endif
00059 }
00060 
00061 void
00062 _IO_un_link (fp)
00063      struct _IO_FILE_plus *fp;
00064 {
00065   if (fp->file._flags & _IO_LINKED)
00066     {
00067       struct _IO_FILE **f;
00068 #ifdef _IO_MTSAFE_IO
00069       _IO_cleanup_region_start_noarg (flush_cleanup);
00070       _IO_lock_lock (list_all_lock);
00071       run_fp = (_IO_FILE *) fp;
00072       _IO_flockfile ((_IO_FILE *) fp);
00073 #endif
00074       if (INTUSE(_IO_list_all) == NULL)
00075        ;
00076       else if (fp == INTUSE(_IO_list_all))
00077        {
00078          INTUSE(_IO_list_all)
00079            = (struct _IO_FILE_plus *) INTUSE(_IO_list_all)->file._chain;
00080          ++_IO_list_all_stamp;
00081        }
00082       else
00083        for (f = &INTUSE(_IO_list_all)->file._chain; *f; f = &(*f)->_chain)
00084          if (*f == (_IO_FILE *) fp)
00085            {
00086              *f = fp->file._chain;
00087              ++_IO_list_all_stamp;
00088              break;
00089            }
00090       fp->file._flags &= ~_IO_LINKED;
00091 #ifdef _IO_MTSAFE_IO
00092       _IO_funlockfile ((_IO_FILE *) fp);
00093       run_fp = NULL;
00094       _IO_lock_unlock (list_all_lock);
00095       _IO_cleanup_region_end (0);
00096 #endif
00097     }
00098 }
00099 INTDEF(_IO_un_link)
00100 
00101 void
00102 _IO_link_in (fp)
00103      struct _IO_FILE_plus *fp;
00104 {
00105   if ((fp->file._flags & _IO_LINKED) == 0)
00106     {
00107       fp->file._flags |= _IO_LINKED;
00108 #ifdef _IO_MTSAFE_IO
00109       _IO_cleanup_region_start_noarg (flush_cleanup);
00110       _IO_lock_lock (list_all_lock);
00111       run_fp = (_IO_FILE *) fp;
00112       _IO_flockfile ((_IO_FILE *) fp);
00113 #endif
00114       fp->file._chain = (_IO_FILE *) INTUSE(_IO_list_all);
00115       INTUSE(_IO_list_all) = fp;
00116       ++_IO_list_all_stamp;
00117 #ifdef _IO_MTSAFE_IO
00118       _IO_funlockfile ((_IO_FILE *) fp);
00119       run_fp = NULL;
00120       _IO_lock_unlock (list_all_lock);
00121       _IO_cleanup_region_end (0);
00122 #endif
00123     }
00124 }
00125 INTDEF(_IO_link_in)
00126 
00127 /* Return minimum _pos markers
00128    Assumes the current get area is the main get area. */
00129 _IO_ssize_t _IO_least_marker (_IO_FILE *fp, char *end_p);
00130 
00131 _IO_ssize_t
00132 _IO_least_marker (fp, end_p)
00133      _IO_FILE *fp;
00134      char *end_p;
00135 {
00136   _IO_ssize_t least_so_far = end_p - fp->_IO_read_base;
00137   struct _IO_marker *mark;
00138   for (mark = fp->_markers; mark != NULL; mark = mark->_next)
00139     if (mark->_pos < least_so_far)
00140       least_so_far = mark->_pos;
00141   return least_so_far;
00142 }
00143 
00144 /* Switch current get area from backup buffer to (start of) main get area. */
00145 
00146 void
00147 _IO_switch_to_main_get_area (fp)
00148      _IO_FILE *fp;
00149 {
00150   char *tmp;
00151   fp->_flags &= ~_IO_IN_BACKUP;
00152   /* Swap _IO_read_end and _IO_save_end. */
00153   tmp = fp->_IO_read_end;
00154   fp->_IO_read_end = fp->_IO_save_end;
00155   fp->_IO_save_end= tmp;
00156   /* Swap _IO_read_base and _IO_save_base. */
00157   tmp = fp->_IO_read_base;
00158   fp->_IO_read_base = fp->_IO_save_base;
00159   fp->_IO_save_base = tmp;
00160   /* Set _IO_read_ptr. */
00161   fp->_IO_read_ptr = fp->_IO_read_base;
00162 }
00163 
00164 /* Switch current get area from main get area to (end of) backup area. */
00165 
00166 void
00167 _IO_switch_to_backup_area (fp)
00168      _IO_FILE *fp;
00169 {
00170   char *tmp;
00171   fp->_flags |= _IO_IN_BACKUP;
00172   /* Swap _IO_read_end and _IO_save_end. */
00173   tmp = fp->_IO_read_end;
00174   fp->_IO_read_end = fp->_IO_save_end;
00175   fp->_IO_save_end = tmp;
00176   /* Swap _IO_read_base and _IO_save_base. */
00177   tmp = fp->_IO_read_base;
00178   fp->_IO_read_base = fp->_IO_save_base;
00179   fp->_IO_save_base = tmp;
00180   /* Set _IO_read_ptr.  */
00181   fp->_IO_read_ptr = fp->_IO_read_end;
00182 }
00183 
00184 int
00185 _IO_switch_to_get_mode (fp)
00186      _IO_FILE *fp;
00187 {
00188   if (fp->_IO_write_ptr > fp->_IO_write_base)
00189     if (_IO_OVERFLOW (fp, EOF) == EOF)
00190       return EOF;
00191   if (_IO_in_backup (fp))
00192     fp->_IO_read_base = fp->_IO_backup_base;
00193   else
00194     {
00195       fp->_IO_read_base = fp->_IO_buf_base;
00196       if (fp->_IO_write_ptr > fp->_IO_read_end)
00197        fp->_IO_read_end = fp->_IO_write_ptr;
00198     }
00199   fp->_IO_read_ptr = fp->_IO_write_ptr;
00200 
00201   fp->_IO_write_base = fp->_IO_write_ptr = fp->_IO_write_end = fp->_IO_read_ptr;
00202 
00203   fp->_flags &= ~_IO_CURRENTLY_PUTTING;
00204   return 0;
00205 }
00206 INTDEF(_IO_switch_to_get_mode)
00207 
00208 void
00209 _IO_free_backup_area (fp)
00210      _IO_FILE *fp;
00211 {
00212   if (_IO_in_backup (fp))
00213     _IO_switch_to_main_get_area (fp);  /* Just in case. */
00214   free (fp->_IO_save_base);
00215   fp->_IO_save_base = NULL;
00216   fp->_IO_save_end = NULL;
00217   fp->_IO_backup_base = NULL;
00218 }
00219 INTDEF(_IO_free_backup_area)
00220 
00221 #if 0
00222 int
00223 _IO_switch_to_put_mode (fp)
00224      _IO_FILE *fp;
00225 {
00226   fp->_IO_write_base = fp->_IO_read_ptr;
00227   fp->_IO_write_ptr = fp->_IO_read_ptr;
00228   /* Following is wrong if line- or un-buffered? */
00229   fp->_IO_write_end = (fp->_flags & _IO_IN_BACKUP
00230                      ? fp->_IO_read_end : fp->_IO_buf_end);
00231 
00232   fp->_IO_read_ptr = fp->_IO_read_end;
00233   fp->_IO_read_base = fp->_IO_read_end;
00234 
00235   fp->_flags |= _IO_CURRENTLY_PUTTING;
00236   return 0;
00237 }
00238 #endif
00239 
00240 int
00241 __overflow (f, ch)
00242      _IO_FILE *f;
00243      int ch;
00244 {
00245   /* This is a single-byte stream.  */
00246   if (f->_mode == 0)
00247     _IO_fwide (f, -1);
00248   return _IO_OVERFLOW (f, ch);
00249 }
00250 libc_hidden_def (__overflow)
00251 
00252 static int save_for_backup (_IO_FILE *fp, char *end_p)
00253 #ifdef _LIBC
00254      internal_function
00255 #endif
00256      ;
00257 
00258 static int
00259 #ifdef _LIBC
00260 internal_function
00261 #endif
00262 save_for_backup (fp, end_p)
00263      _IO_FILE *fp;
00264      char *end_p;
00265 {
00266   /* Append [_IO_read_base..end_p] to backup area. */
00267   _IO_ssize_t least_mark = _IO_least_marker (fp, end_p);
00268   /* needed_size is how much space we need in the backup area. */
00269   _IO_size_t needed_size = (end_p - fp->_IO_read_base) - least_mark;
00270   /* FIXME: Dubious arithmetic if pointers are NULL */
00271   _IO_size_t current_Bsize = fp->_IO_save_end - fp->_IO_save_base;
00272   _IO_size_t avail; /* Extra space available for future expansion. */
00273   _IO_ssize_t delta;
00274   struct _IO_marker *mark;
00275   if (needed_size > current_Bsize)
00276     {
00277       char *new_buffer;
00278       avail = 100;
00279       new_buffer = (char *) malloc (avail + needed_size);
00280       if (new_buffer == NULL)
00281        return EOF;          /* FIXME */
00282       if (least_mark < 0)
00283        {
00284 #ifdef _LIBC
00285          __mempcpy (__mempcpy (new_buffer + avail,
00286                             fp->_IO_save_end + least_mark,
00287                             -least_mark),
00288                    fp->_IO_read_base,
00289                    end_p - fp->_IO_read_base);
00290 #else
00291          memcpy (new_buffer + avail,
00292                 fp->_IO_save_end + least_mark,
00293                 -least_mark);
00294          memcpy (new_buffer + avail - least_mark,
00295                 fp->_IO_read_base,
00296                 end_p - fp->_IO_read_base);
00297 #endif
00298        }
00299       else
00300        memcpy (new_buffer + avail,
00301               fp->_IO_read_base + least_mark,
00302               needed_size);
00303       free (fp->_IO_save_base);
00304       fp->_IO_save_base = new_buffer;
00305       fp->_IO_save_end = new_buffer + avail + needed_size;
00306     }
00307   else
00308     {
00309       avail = current_Bsize - needed_size;
00310       if (least_mark < 0)
00311        {
00312          memmove (fp->_IO_save_base + avail,
00313                  fp->_IO_save_end + least_mark,
00314                  -least_mark);
00315          memcpy (fp->_IO_save_base + avail - least_mark,
00316                 fp->_IO_read_base,
00317                 end_p - fp->_IO_read_base);
00318        }
00319       else if (needed_size > 0)
00320        memcpy (fp->_IO_save_base + avail,
00321               fp->_IO_read_base + least_mark,
00322               needed_size);
00323     }
00324   fp->_IO_backup_base = fp->_IO_save_base + avail;
00325   /* Adjust all the streammarkers. */
00326   delta = end_p - fp->_IO_read_base;
00327   for (mark = fp->_markers; mark != NULL; mark = mark->_next)
00328     mark->_pos -= delta;
00329   return 0;
00330 }
00331 
00332 int
00333 __underflow (fp)
00334      _IO_FILE *fp;
00335 {
00336 #if defined _LIBC || defined _GLIBCPP_USE_WCHAR_T
00337   if (_IO_vtable_offset (fp) == 0 && _IO_fwide (fp, -1) != -1)
00338     return EOF;
00339 #endif
00340 
00341   if (fp->_mode == 0)
00342     _IO_fwide (fp, -1);
00343   if (_IO_in_put_mode (fp))
00344     if (INTUSE(_IO_switch_to_get_mode) (fp) == EOF)
00345       return EOF;
00346   if (fp->_IO_read_ptr < fp->_IO_read_end)
00347     return *(unsigned char *) fp->_IO_read_ptr;
00348   if (_IO_in_backup (fp))
00349     {
00350       _IO_switch_to_main_get_area (fp);
00351       if (fp->_IO_read_ptr < fp->_IO_read_end)
00352        return *(unsigned char *) fp->_IO_read_ptr;
00353     }
00354   if (_IO_have_markers (fp))
00355     {
00356       if (save_for_backup (fp, fp->_IO_read_end))
00357        return EOF;
00358     }
00359   else if (_IO_have_backup (fp))
00360     INTUSE(_IO_free_backup_area) (fp);
00361   return _IO_UNDERFLOW (fp);
00362 }
00363 libc_hidden_def (__underflow)
00364 
00365 int
00366 __uflow (fp)
00367      _IO_FILE *fp;
00368 {
00369 #if defined _LIBC || defined _GLIBCPP_USE_WCHAR_T
00370   if (_IO_vtable_offset (fp) == 0 && _IO_fwide (fp, -1) != -1)
00371     return EOF;
00372 #endif
00373 
00374   if (fp->_mode == 0)
00375     _IO_fwide (fp, -1);
00376   if (_IO_in_put_mode (fp))
00377     if (INTUSE(_IO_switch_to_get_mode) (fp) == EOF)
00378       return EOF;
00379   if (fp->_IO_read_ptr < fp->_IO_read_end)
00380     return *(unsigned char *) fp->_IO_read_ptr++;
00381   if (_IO_in_backup (fp))
00382     {
00383       _IO_switch_to_main_get_area (fp);
00384       if (fp->_IO_read_ptr < fp->_IO_read_end)
00385        return *(unsigned char *) fp->_IO_read_ptr++;
00386     }
00387   if (_IO_have_markers (fp))
00388     {
00389       if (save_for_backup (fp, fp->_IO_read_end))
00390        return EOF;
00391     }
00392   else if (_IO_have_backup (fp))
00393     INTUSE(_IO_free_backup_area) (fp);
00394   return _IO_UFLOW (fp);
00395 }
00396 libc_hidden_def (__uflow)
00397 
00398 void
00399 _IO_setb (f, b, eb, a)
00400      _IO_FILE *f;
00401      char *b;
00402      char *eb;
00403      int a;
00404 {
00405   if (f->_IO_buf_base && !(f->_flags & _IO_USER_BUF))
00406     FREE_BUF (f->_IO_buf_base, _IO_blen (f));
00407   f->_IO_buf_base = b;
00408   f->_IO_buf_end = eb;
00409   if (a)
00410     f->_flags &= ~_IO_USER_BUF;
00411   else
00412     f->_flags |= _IO_USER_BUF;
00413 }
00414 INTDEF(_IO_setb)
00415 
00416 void
00417 _IO_doallocbuf (fp)
00418      _IO_FILE *fp;
00419 {
00420   if (fp->_IO_buf_base)
00421     return;
00422   if (!(fp->_flags & _IO_UNBUFFERED) || fp->_mode > 0)
00423     if (_IO_DOALLOCATE (fp) != EOF)
00424       return;
00425   INTUSE(_IO_setb) (fp, fp->_shortbuf, fp->_shortbuf+1, 0);
00426 }
00427 INTDEF(_IO_doallocbuf)
00428 
00429 int
00430 _IO_default_underflow (fp)
00431      _IO_FILE *fp;
00432 {
00433   return EOF;
00434 }
00435 
00436 int
00437 _IO_default_uflow (fp)
00438      _IO_FILE *fp;
00439 {
00440   int ch = _IO_UNDERFLOW (fp);
00441   if (ch == EOF)
00442     return EOF;
00443   return *(unsigned char *) fp->_IO_read_ptr++;
00444 }
00445 INTDEF(_IO_default_uflow)
00446 
00447 _IO_size_t
00448 _IO_default_xsputn (f, data, n)
00449      _IO_FILE *f;
00450      const void *data;
00451      _IO_size_t n;
00452 {
00453   const char *s = (char *) data;
00454   _IO_size_t more = n;
00455   if (more <= 0)
00456     return 0;
00457   for (;;)
00458     {
00459       /* Space available. */
00460       if (f->_IO_write_ptr < f->_IO_write_end)
00461        {
00462          _IO_size_t count = f->_IO_write_end - f->_IO_write_ptr;
00463          if (count > more)
00464            count = more;
00465          if (count > 20)
00466            {
00467 #ifdef _LIBC
00468              f->_IO_write_ptr = __mempcpy (f->_IO_write_ptr, s, count);
00469 #else
00470              memcpy (f->_IO_write_ptr, s, count);
00471              f->_IO_write_ptr += count;
00472 #endif
00473              s += count;
00474             }
00475          else if (count)
00476            {
00477              char *p = f->_IO_write_ptr;
00478              _IO_ssize_t i;
00479              for (i = count; --i >= 0; )
00480               *p++ = *s++;
00481              f->_IO_write_ptr = p;
00482             }
00483          more -= count;
00484         }
00485       if (more == 0 || _IO_OVERFLOW (f, (unsigned char) *s++) == EOF)
00486        break;
00487       more--;
00488     }
00489   return n - more;
00490 }
00491 INTDEF(_IO_default_xsputn)
00492 
00493 _IO_size_t
00494 _IO_sgetn (fp, data, n)
00495      _IO_FILE *fp;
00496      void *data;
00497      _IO_size_t n;
00498 {
00499   /* FIXME handle putback buffer here! */
00500   return _IO_XSGETN (fp, data, n);
00501 }
00502 INTDEF(_IO_sgetn)
00503 
00504 _IO_size_t
00505 _IO_default_xsgetn (fp, data, n)
00506      _IO_FILE *fp;
00507      void *data;
00508      _IO_size_t n;
00509 {
00510   _IO_size_t more = n;
00511   char *s = (char*) data;
00512   for (;;)
00513     {
00514       /* Data available. */
00515       if (fp->_IO_read_ptr < fp->_IO_read_end)
00516        {
00517          _IO_size_t count = fp->_IO_read_end - fp->_IO_read_ptr;
00518          if (count > more)
00519            count = more;
00520          if (count > 20)
00521            {
00522 #ifdef _LIBC
00523              s = __mempcpy (s, fp->_IO_read_ptr, count);
00524 #else
00525              memcpy (s, fp->_IO_read_ptr, count);
00526              s += count;
00527 #endif
00528              fp->_IO_read_ptr += count;
00529            }
00530          else if (count)
00531            {
00532              char *p = fp->_IO_read_ptr;
00533              int i = (int) count;
00534              while (--i >= 0)
00535               *s++ = *p++;
00536              fp->_IO_read_ptr = p;
00537             }
00538             more -= count;
00539         }
00540       if (more == 0 || __underflow (fp) == EOF)
00541        break;
00542     }
00543   return n - more;
00544 }
00545 INTDEF(_IO_default_xsgetn)
00546 
00547 #if 0
00548 /* Seems not to be needed. --drepper */
00549 int
00550 _IO_sync (fp)
00551      _IO_FILE *fp;
00552 {
00553   return 0;
00554 }
00555 #endif
00556 
00557 _IO_FILE *
00558 _IO_default_setbuf (fp, p, len)
00559      _IO_FILE *fp;
00560      char *p;
00561      _IO_ssize_t len;
00562 {
00563     if (_IO_SYNC (fp) == EOF)
00564        return NULL;
00565     if (p == NULL || len == 0)
00566       {
00567        fp->_flags |= _IO_UNBUFFERED;
00568        INTUSE(_IO_setb) (fp, fp->_shortbuf, fp->_shortbuf+1, 0);
00569       }
00570     else
00571       {
00572        fp->_flags &= ~_IO_UNBUFFERED;
00573        INTUSE(_IO_setb) (fp, p, p+len, 0);
00574       }
00575     fp->_IO_write_base = fp->_IO_write_ptr = fp->_IO_write_end = 0;
00576     fp->_IO_read_base = fp->_IO_read_ptr = fp->_IO_read_end = 0;
00577     return fp;
00578 }
00579 
00580 _IO_off64_t
00581 _IO_default_seekpos (fp, pos, mode)
00582      _IO_FILE *fp;
00583      _IO_off64_t pos;
00584      int mode;
00585 {
00586   return _IO_SEEKOFF (fp, pos, 0, mode);
00587 }
00588 
00589 int
00590 _IO_default_doallocate (fp)
00591      _IO_FILE *fp;
00592 {
00593   char *buf;
00594 
00595   ALLOC_BUF (buf, _IO_BUFSIZ, EOF);
00596   INTUSE(_IO_setb) (fp, buf, buf+_IO_BUFSIZ, 1);
00597   return 1;
00598 }
00599 INTDEF(_IO_default_doallocate)
00600 
00601 void
00602 _IO_init (fp, flags)
00603      _IO_FILE *fp;
00604      int flags;
00605 {
00606   _IO_no_init (fp, flags, -1, NULL, NULL);
00607 }
00608 INTDEF(_IO_init)
00609 
00610 void
00611 _IO_old_init (fp, flags)
00612      _IO_FILE *fp;
00613      int flags;
00614 {
00615   fp->_flags = _IO_MAGIC|flags;
00616   fp->_flags2 = 0;
00617   fp->_IO_buf_base = NULL;
00618   fp->_IO_buf_end = NULL;
00619   fp->_IO_read_base = NULL;
00620   fp->_IO_read_ptr = NULL;
00621   fp->_IO_read_end = NULL;
00622   fp->_IO_write_base = NULL;
00623   fp->_IO_write_ptr = NULL;
00624   fp->_IO_write_end = NULL;
00625   fp->_chain = NULL; /* Not necessary. */
00626 
00627   fp->_IO_save_base = NULL;
00628   fp->_IO_backup_base = NULL;
00629   fp->_IO_save_end = NULL;
00630   fp->_markers = NULL;
00631   fp->_cur_column = 0;
00632 #if _IO_JUMPS_OFFSET
00633   fp->_vtable_offset = 0;
00634 #endif
00635 #ifdef _IO_MTSAFE_IO
00636   if (fp->_lock != NULL)
00637     _IO_lock_init (*fp->_lock);
00638 #endif
00639 }
00640 
00641 void
00642 _IO_no_init (fp, flags, orientation, wd, jmp)
00643      _IO_FILE *fp;
00644      int flags;
00645      int orientation;
00646      struct _IO_wide_data *wd;
00647      const struct _IO_jump_t *jmp;
00648 {
00649   _IO_old_init (fp, flags);
00650   fp->_mode = orientation;
00651 #if defined _LIBC || defined _GLIBCPP_USE_WCHAR_T
00652   if (orientation >= 0)
00653     {
00654       fp->_wide_data = wd;
00655       fp->_wide_data->_IO_buf_base = NULL;
00656       fp->_wide_data->_IO_buf_end = NULL;
00657       fp->_wide_data->_IO_read_base = NULL;
00658       fp->_wide_data->_IO_read_ptr = NULL;
00659       fp->_wide_data->_IO_read_end = NULL;
00660       fp->_wide_data->_IO_write_base = NULL;
00661       fp->_wide_data->_IO_write_ptr = NULL;
00662       fp->_wide_data->_IO_write_end = NULL;
00663       fp->_wide_data->_IO_save_base = NULL;
00664       fp->_wide_data->_IO_backup_base = NULL;
00665       fp->_wide_data->_IO_save_end = NULL;
00666 
00667       fp->_wide_data->_wide_vtable = jmp;
00668     }
00669 #endif
00670   fp->_freeres_list = NULL;
00671 }
00672 
00673 int
00674 _IO_default_sync (fp)
00675      _IO_FILE *fp;
00676 {
00677   return 0;
00678 }
00679 
00680 /* The way the C++ classes are mapped into the C functions in the
00681    current implementation, this function can get called twice! */
00682 
00683 void
00684 _IO_default_finish (fp, dummy)
00685      _IO_FILE *fp;
00686      int dummy;
00687 {
00688   struct _IO_marker *mark;
00689   if (fp->_IO_buf_base && !(fp->_flags & _IO_USER_BUF))
00690     {
00691       FREE_BUF (fp->_IO_buf_base, _IO_blen (fp));
00692       fp->_IO_buf_base = fp->_IO_buf_end = NULL;
00693     }
00694 
00695   for (mark = fp->_markers; mark != NULL; mark = mark->_next)
00696     mark->_sbuf = NULL;
00697 
00698   if (fp->_IO_save_base)
00699     {
00700       free (fp->_IO_save_base);
00701       fp->_IO_save_base = NULL;
00702     }
00703 
00704   INTUSE(_IO_un_link) ((struct _IO_FILE_plus *) fp);
00705 
00706 #ifdef _IO_MTSAFE_IO
00707   if (fp->_lock != NULL)
00708     _IO_lock_fini (*fp->_lock);
00709 #endif
00710 }
00711 INTDEF(_IO_default_finish)
00712 
00713 _IO_off64_t
00714 _IO_default_seekoff (fp, offset, dir, mode)
00715      _IO_FILE *fp;
00716      _IO_off64_t offset;
00717      int dir;
00718      int mode;
00719 {
00720   return _IO_pos_BAD;
00721 }
00722 
00723 int
00724 _IO_sputbackc (fp, c)
00725      _IO_FILE *fp;
00726      int c;
00727 {
00728   int result;
00729 
00730   if (fp->_IO_read_ptr > fp->_IO_read_base
00731       && (unsigned char)fp->_IO_read_ptr[-1] == (unsigned char)c)
00732     {
00733       fp->_IO_read_ptr--;
00734       result = (unsigned char) c;
00735     }
00736   else
00737     result = _IO_PBACKFAIL (fp, c);
00738 
00739   if (result != EOF)
00740     fp->_flags &= ~_IO_EOF_SEEN;
00741 
00742   return result;
00743 }
00744 INTDEF(_IO_sputbackc)
00745 
00746 int
00747 _IO_sungetc (fp)
00748      _IO_FILE *fp;
00749 {
00750   int result;
00751 
00752   if (fp->_IO_read_ptr > fp->_IO_read_base)
00753     {
00754       fp->_IO_read_ptr--;
00755       result = (unsigned char) *fp->_IO_read_ptr;
00756     }
00757   else
00758     result = _IO_PBACKFAIL (fp, EOF);
00759 
00760   if (result != EOF)
00761     fp->_flags &= ~_IO_EOF_SEEN;
00762 
00763   return result;
00764 }
00765 
00766 #if 0 /* Work in progress */
00767 /* Seems not to be needed.  */
00768 #if 0
00769 void
00770 _IO_set_column (fp, c)
00771      _IO_FILE *fp;
00772      int c;
00773 {
00774   if (c == -1)
00775     fp->_column = -1;
00776   else
00777     fp->_column = c - (fp->_IO_write_ptr - fp->_IO_write_base);
00778 }
00779 #else
00780 int
00781 _IO_set_column (fp, i)
00782      _IO_FILE *fp;
00783      int i;
00784 {
00785   fp->_cur_column = i + 1;
00786   return 0;
00787 }
00788 #endif
00789 #endif
00790 
00791 
00792 unsigned
00793 _IO_adjust_column (start, line, count)
00794      unsigned start;
00795      const char *line;
00796      int count;
00797 {
00798   const char *ptr = line + count;
00799   while (ptr > line)
00800     if (*--ptr == '\n')
00801       return line + count - ptr - 1;
00802   return start + count;
00803 }
00804 INTDEF(_IO_adjust_column)
00805 
00806 #if 0
00807 /* Seems not to be needed. --drepper */
00808 int
00809 _IO_get_column (fp)
00810      _IO_FILE *fp;
00811 {
00812   if (fp->_cur_column)
00813     return _IO_adjust_column (fp->_cur_column - 1,
00814                            fp->_IO_write_base,
00815                            fp->_IO_write_ptr - fp->_IO_write_base);
00816   return -1;
00817 }
00818 #endif
00819 
00820 
00821 int
00822 _IO_flush_all_lockp (int do_lock)
00823 {
00824   int result = 0;
00825   struct _IO_FILE *fp;
00826   int last_stamp;
00827 
00828 #ifdef _IO_MTSAFE_IO
00829   _IO_cleanup_region_start_noarg (flush_cleanup);
00830   if (do_lock)
00831     _IO_lock_lock (list_all_lock);
00832 #endif
00833 
00834   last_stamp = _IO_list_all_stamp;
00835   fp = (_IO_FILE *) INTUSE(_IO_list_all);
00836   while (fp != NULL)
00837     {
00838       run_fp = fp;
00839       if (do_lock)
00840        _IO_flockfile (fp);
00841 
00842       if (((fp->_mode <= 0 && fp->_IO_write_ptr > fp->_IO_write_base)
00843 #if defined _LIBC || defined _GLIBCPP_USE_WCHAR_T
00844           || (_IO_vtable_offset (fp) == 0
00845               && fp->_mode > 0 && (fp->_wide_data->_IO_write_ptr
00846                                 > fp->_wide_data->_IO_write_base))
00847 #endif
00848           )
00849          && _IO_OVERFLOW (fp, EOF) == EOF)
00850        result = EOF;
00851 
00852       if (do_lock)
00853        _IO_funlockfile (fp);
00854       run_fp = NULL;
00855 
00856       if (last_stamp != _IO_list_all_stamp)
00857        {
00858          /* Something was added to the list.  Start all over again.  */
00859          fp = (_IO_FILE *) INTUSE(_IO_list_all);
00860          last_stamp = _IO_list_all_stamp;
00861        }
00862       else
00863        fp = fp->_chain;
00864     }
00865 
00866 #ifdef _IO_MTSAFE_IO
00867   if (do_lock)
00868     _IO_lock_unlock (list_all_lock);
00869   _IO_cleanup_region_end (0);
00870 #endif
00871 
00872   return result;
00873 }
00874 
00875 
00876 int
00877 _IO_flush_all ()
00878 {
00879   /* We want locking.  */
00880   return _IO_flush_all_lockp (1);
00881 }
00882 INTDEF(_IO_flush_all)
00883 
00884 void
00885 _IO_flush_all_linebuffered ()
00886 {
00887   struct _IO_FILE *fp;
00888   int last_stamp;
00889 
00890 #ifdef _IO_MTSAFE_IO
00891   _IO_cleanup_region_start_noarg (flush_cleanup);
00892   _IO_lock_lock (list_all_lock);
00893 #endif
00894 
00895   last_stamp = _IO_list_all_stamp;
00896   fp = (_IO_FILE *) INTUSE(_IO_list_all);
00897   while (fp != NULL)
00898     {
00899       run_fp = fp;
00900       _IO_flockfile (fp);
00901 
00902       if ((fp->_flags & _IO_NO_WRITES) == 0 && fp->_flags & _IO_LINE_BUF)
00903        _IO_OVERFLOW (fp, EOF);
00904 
00905       _IO_funlockfile (fp);
00906       run_fp = NULL;
00907 
00908       if (last_stamp != _IO_list_all_stamp)
00909        {
00910          /* Something was added to the list.  Start all over again.  */
00911          fp = (_IO_FILE *) INTUSE(_IO_list_all);
00912          last_stamp = _IO_list_all_stamp;
00913        }
00914       else
00915        fp = fp->_chain;
00916     }
00917 
00918 #ifdef _IO_MTSAFE_IO
00919   _IO_lock_unlock (list_all_lock);
00920   _IO_cleanup_region_end (0);
00921 #endif
00922 }
00923 INTDEF(_IO_flush_all_linebuffered)
00924 #ifdef _LIBC
00925 weak_alias (_IO_flush_all_linebuffered, _flushlbf)
00926 #endif
00927 
00928 
00929 /* The following is a bit tricky.  In general, we want to unbuffer the
00930    streams so that all output which follows is seen.  If we are not
00931    looking for memory leaks it does not make much sense to free the
00932    actual buffer because this will happen anyway once the program
00933    terminated.  If we do want to look for memory leaks we have to free
00934    the buffers.  Whether something is freed is determined by the
00935    function sin the libc_freeres section.  Those are called as part of
00936    the atexit routine, just like _IO_cleanup.  The problem is we do
00937    not know whether the freeres code is called first or _IO_cleanup.
00938    if the former is the case, we set the DEALLOC_BUFFER variable to
00939    true and _IO_unbuffer_write will take care of the rest.  If
00940    _IO_unbuffer_write is called first we add the streams to a list
00941    which the freeres function later can walk through.  */
00942 static void _IO_unbuffer_write (void);
00943 
00944 static bool dealloc_buffers;
00945 static _IO_FILE *freeres_list;
00946 
00947 static void
00948 _IO_unbuffer_write (void)
00949 {
00950   struct _IO_FILE *fp;
00951   for (fp = (_IO_FILE *) INTUSE(_IO_list_all); fp; fp = fp->_chain)
00952     {
00953       if (! (fp->_flags & _IO_UNBUFFERED)
00954          && (! (fp->_flags & _IO_NO_WRITES)
00955              || (fp->_flags & _IO_IS_APPENDING))
00956          /* Iff stream is un-orientated, it wasn't used. */
00957          && fp->_mode != 0)
00958        {
00959          int cnt;
00960 #define MAXTRIES 2
00961          for (cnt = 0; cnt < MAXTRIES; ++cnt)
00962            if (_IO_lock_trylock (*fp->_lock) == 0)
00963              break;
00964            else
00965              /* Give the other thread time to finish up its use of the
00966                stream.  */
00967              __sched_yield ();
00968 
00969          if (! dealloc_buffers && !(fp->_flags & _IO_USER_BUF))
00970            {
00971              fp->_flags |= _IO_USER_BUF;
00972 
00973              fp->_freeres_list = freeres_list;
00974              freeres_list = fp;
00975              fp->_freeres_buf = fp->_IO_buf_base;
00976              fp->_freeres_size = _IO_blen (fp);
00977            }
00978 
00979          _IO_SETBUF (fp, NULL, 0);
00980 
00981          if (cnt < MAXTRIES)
00982            _IO_lock_unlock (*fp->_lock);
00983        }
00984 
00985       /* Make sure that never again the wide char functions can be
00986         used.  */
00987       fp->_mode = -1;
00988     }
00989 }
00990 
00991 
00992 libc_freeres_fn (buffer_free)
00993 {
00994   dealloc_buffers = true;
00995 
00996   while (freeres_list != NULL)
00997     {
00998       FREE_BUF (freeres_list->_freeres_buf, freeres_list->_freeres_size);
00999 
01000       freeres_list = freeres_list->_freeres_list;
01001     }
01002 }
01003 
01004 
01005 int
01006 _IO_cleanup ()
01007 {
01008   /* We do *not* want locking.  Some threads might use streams but
01009      that is their problem, we flush them underneath them.  */
01010   int result = _IO_flush_all_lockp (0);
01011 
01012   /* We currently don't have a reliable mechanism for making sure that
01013      C++ static destructors are executed in the correct order.
01014      So it is possible that other static destructors might want to
01015      write to cout - and they're supposed to be able to do so.
01016 
01017      The following will make the standard streambufs be unbuffered,
01018      which forces any output from late destructors to be written out. */
01019   _IO_unbuffer_write ();
01020 
01021   return result;
01022 }
01023 
01024 
01025 void
01026 _IO_init_marker (marker, fp)
01027      struct _IO_marker *marker;
01028      _IO_FILE *fp;
01029 {
01030   marker->_sbuf = fp;
01031   if (_IO_in_put_mode (fp))
01032     INTUSE(_IO_switch_to_get_mode) (fp);
01033   if (_IO_in_backup (fp))
01034     marker->_pos = fp->_IO_read_ptr - fp->_IO_read_end;
01035   else
01036     marker->_pos = fp->_IO_read_ptr - fp->_IO_read_base;
01037 
01038   /* Should perhaps sort the chain? */
01039   marker->_next = fp->_markers;
01040   fp->_markers = marker;
01041 }
01042 
01043 void
01044 _IO_remove_marker (marker)
01045      struct _IO_marker *marker;
01046 {
01047   /* Unlink from sb's chain. */
01048   struct _IO_marker **ptr = &marker->_sbuf->_markers;
01049   for (; ; ptr = &(*ptr)->_next)
01050     {
01051       if (*ptr == NULL)
01052        break;
01053       else if (*ptr == marker)
01054        {
01055          *ptr = marker->_next;
01056          return;
01057        }
01058     }
01059 #if 0
01060     if _sbuf has a backup area that is no longer needed, should we delete
01061     it now, or wait until the next underflow?
01062 #endif
01063 }
01064 
01065 #define BAD_DELTA EOF
01066 
01067 int
01068 _IO_marker_difference (mark1, mark2)
01069      struct _IO_marker *mark1;
01070      struct _IO_marker *mark2;
01071 {
01072   return mark1->_pos - mark2->_pos;
01073 }
01074 
01075 /* Return difference between MARK and current position of MARK's stream. */
01076 int
01077 _IO_marker_delta (mark)
01078      struct _IO_marker *mark;
01079 {
01080   int cur_pos;
01081   if (mark->_sbuf == NULL)
01082     return BAD_DELTA;
01083   if (_IO_in_backup (mark->_sbuf))
01084     cur_pos = mark->_sbuf->_IO_read_ptr - mark->_sbuf->_IO_read_end;
01085   else
01086     cur_pos = mark->_sbuf->_IO_read_ptr - mark->_sbuf->_IO_read_base;
01087   return mark->_pos - cur_pos;
01088 }
01089 
01090 int
01091 _IO_seekmark (fp, mark, delta)
01092      _IO_FILE *fp;
01093      struct _IO_marker *mark;
01094      int delta;
01095 {
01096   if (mark->_sbuf != fp)
01097     return EOF;
01098  if (mark->_pos >= 0)
01099     {
01100       if (_IO_in_backup (fp))
01101        _IO_switch_to_main_get_area (fp);
01102       fp->_IO_read_ptr = fp->_IO_read_base + mark->_pos;
01103     }
01104   else
01105     {
01106       if (!_IO_in_backup (fp))
01107        _IO_switch_to_backup_area (fp);
01108       fp->_IO_read_ptr = fp->_IO_read_end + mark->_pos;
01109     }
01110   return 0;
01111 }
01112 
01113 void
01114 _IO_unsave_markers (fp)
01115      _IO_FILE *fp;
01116 {
01117   struct _IO_marker *mark = fp->_markers;
01118   if (mark)
01119     {
01120 #ifdef TODO
01121       streampos offset = seekoff (0, ios::cur, ios::in);
01122       if (offset != EOF)
01123        {
01124          offset += eGptr () - Gbase ();
01125          for ( ; mark != NULL; mark = mark->_next)
01126            mark->set_streampos (mark->_pos + offset);
01127        }
01128     else
01129       {
01130        for ( ; mark != NULL; mark = mark->_next)
01131          mark->set_streampos (EOF);
01132       }
01133 #endif
01134       fp->_markers = 0;
01135     }
01136 
01137   if (_IO_have_backup (fp))
01138     INTUSE(_IO_free_backup_area) (fp);
01139 }
01140 INTDEF(_IO_unsave_markers)
01141 
01142 #if 0
01143 /* Seems not to be needed. --drepper */
01144 int
01145 _IO_nobackup_pbackfail (fp, c)
01146      _IO_FILE *fp;
01147      int c;
01148 {
01149   if (fp->_IO_read_ptr > fp->_IO_read_base)
01150        fp->_IO_read_ptr--;
01151   if (c != EOF && *fp->_IO_read_ptr != c)
01152       *fp->_IO_read_ptr = c;
01153   return (unsigned char) c;
01154 }
01155 #endif
01156 
01157 int
01158 _IO_default_pbackfail (fp, c)
01159      _IO_FILE *fp;
01160      int c;
01161 {
01162   if (fp->_IO_read_ptr > fp->_IO_read_base && !_IO_in_backup (fp)
01163       && (unsigned char) fp->_IO_read_ptr[-1] == c)
01164     --fp->_IO_read_ptr;
01165   else
01166     {
01167       /* Need to handle a filebuf in write mode (switch to read mode). FIXME!*/
01168       if (!_IO_in_backup (fp))
01169        {
01170          /* We need to keep the invariant that the main get area
01171             logically follows the backup area.  */
01172          if (fp->_IO_read_ptr > fp->_IO_read_base && _IO_have_backup (fp))
01173            {
01174              if (save_for_backup (fp, fp->_IO_read_ptr))
01175               return EOF;
01176            }
01177          else if (!_IO_have_backup (fp))
01178            {
01179              /* No backup buffer: allocate one. */
01180              /* Use nshort buffer, if unused? (probably not)  FIXME */
01181              int backup_size = 128;
01182              char *bbuf = (char *) malloc (backup_size);
01183              if (bbuf == NULL)
01184               return EOF;
01185              fp->_IO_save_base = bbuf;
01186              fp->_IO_save_end = fp->_IO_save_base + backup_size;
01187              fp->_IO_backup_base = fp->_IO_save_end;
01188            }
01189          fp->_IO_read_base = fp->_IO_read_ptr;
01190          _IO_switch_to_backup_area (fp);
01191        }
01192       else if (fp->_IO_read_ptr <= fp->_IO_read_base)
01193        {
01194          /* Increase size of existing backup buffer. */
01195          _IO_size_t new_size;
01196          _IO_size_t old_size = fp->_IO_read_end - fp->_IO_read_base;
01197          char *new_buf;
01198          new_size = 2 * old_size;
01199          new_buf = (char *) malloc (new_size);
01200          if (new_buf == NULL)
01201            return EOF;
01202          memcpy (new_buf + (new_size - old_size), fp->_IO_read_base,
01203                 old_size);
01204          free (fp->_IO_read_base);
01205          _IO_setg (fp, new_buf, new_buf + (new_size - old_size),
01206                   new_buf + new_size);
01207          fp->_IO_backup_base = fp->_IO_read_ptr;
01208        }
01209 
01210       *--fp->_IO_read_ptr = c;
01211     }
01212   return (unsigned char) c;
01213 }
01214 INTDEF(_IO_default_pbackfail)
01215 
01216 _IO_off64_t
01217 _IO_default_seek (fp, offset, dir)
01218      _IO_FILE *fp;
01219      _IO_off64_t offset;
01220      int dir;
01221 {
01222   return _IO_pos_BAD;
01223 }
01224 
01225 int
01226 _IO_default_stat (fp, st)
01227      _IO_FILE *fp;
01228      void* st;
01229 {
01230   return EOF;
01231 }
01232 
01233 _IO_ssize_t
01234 _IO_default_read (fp, data, n)
01235      _IO_FILE* fp;
01236      void *data;
01237      _IO_ssize_t n;
01238 {
01239   return -1;
01240 }
01241 
01242 _IO_ssize_t
01243 _IO_default_write (fp, data, n)
01244      _IO_FILE *fp;
01245      const void *data;
01246      _IO_ssize_t n;
01247 {
01248   return 0;
01249 }
01250 
01251 int
01252 _IO_default_showmanyc (fp)
01253      _IO_FILE *fp;
01254 {
01255   return -1;
01256 }
01257 
01258 void
01259 _IO_default_imbue (fp, locale)
01260      _IO_FILE *fp;
01261      void *locale;
01262 {
01263 }
01264 
01265 _IO_ITER
01266 _IO_iter_begin()
01267 {
01268   return (_IO_ITER) INTUSE(_IO_list_all);
01269 }
01270 libc_hidden_def (_IO_iter_begin)
01271 
01272 _IO_ITER
01273 _IO_iter_end()
01274 {
01275   return NULL;
01276 }
01277 libc_hidden_def (_IO_iter_end)
01278 
01279 _IO_ITER
01280 _IO_iter_next(iter)
01281     _IO_ITER iter;
01282 {
01283   return iter->_chain;
01284 }
01285 libc_hidden_def (_IO_iter_next)
01286 
01287 _IO_FILE *
01288 _IO_iter_file(iter)
01289     _IO_ITER iter;
01290 {
01291   return iter;
01292 }
01293 libc_hidden_def (_IO_iter_file)
01294 
01295 void
01296 _IO_list_lock()
01297 {
01298 #ifdef _IO_MTSAFE_IO
01299   _IO_lock_lock (list_all_lock);
01300 #endif
01301 }
01302 libc_hidden_def (_IO_list_lock)
01303 
01304 void
01305 _IO_list_unlock()
01306 {
01307 #ifdef _IO_MTSAFE_IO
01308   _IO_lock_unlock (list_all_lock);
01309 #endif
01310 }
01311 libc_hidden_def (_IO_list_unlock)
01312 
01313 void
01314 _IO_list_resetlock()
01315 {
01316 #ifdef _IO_MTSAFE_IO
01317   _IO_lock_init (list_all_lock);
01318 #endif
01319 }
01320 libc_hidden_def (_IO_list_resetlock)
01321 
01322 
01323 #ifdef TODO
01324 #if defined(linux)
01325 #define IO_CLEANUP ;
01326 #endif
01327 
01328 #ifdef IO_CLEANUP
01329   IO_CLEANUP
01330 #else
01331 struct __io_defs {
01332     __io_defs() { }
01333     ~__io_defs() { _IO_cleanup (); }
01334 };
01335 __io_defs io_defs__;
01336 #endif
01337 
01338 #endif /* TODO */
01339 
01340 #ifdef text_set_element
01341 text_set_element(__libc_atexit, _IO_cleanup);
01342 #endif