(root)/
glibc-2.38/
libio/
wgenops.c
       1  /* Copyright (C) 1993-2023 Free Software Foundation, Inc.
       2     This file is part of the GNU C Library.
       3  
       4     The GNU C Library is free software; you can redistribute it and/or
       5     modify it under the terms of the GNU Lesser General Public
       6     License as published by the Free Software Foundation; either
       7     version 2.1 of the License, or (at your option) any later version.
       8  
       9     The GNU C Library is distributed in the hope that it will be useful,
      10     but WITHOUT ANY WARRANTY; without even the implied warranty of
      11     MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
      12     Lesser General Public License for more details.
      13  
      14     You should have received a copy of the GNU Lesser General Public
      15     License along with the GNU C Library; if not, see
      16     <https://www.gnu.org/licenses/>.
      17  
      18     As a special exception, if you link the code in this file with
      19     files compiled with a GNU compiler to produce an executable,
      20     that does not cause the resulting executable to be covered by
      21     the GNU Lesser General Public License.  This exception does not
      22     however invalidate any other reasons why the executable file
      23     might be covered by the GNU Lesser General Public License.
      24     This exception applies to code released by its copyright holders
      25     in files containing the exception.  */
      26  
      27  /* Generic or default I/O operations. */
      28  
      29  #include "libioP.h"
      30  #include <stdlib.h>
      31  #include <string.h>
      32  #include <wchar.h>
      33  
      34  
      35  static int save_for_wbackup (FILE *fp, wchar_t *end_p) __THROW;
      36  
      37  /* Return minimum _pos markers
      38     Assumes the current get area is the main get area. */
      39  ssize_t
      40  _IO_least_wmarker (FILE *fp, wchar_t *end_p)
      41  {
      42    ssize_t least_so_far = end_p - fp->_wide_data->_IO_read_base;
      43    struct _IO_marker *mark;
      44    for (mark = fp->_markers; mark != NULL; mark = mark->_next)
      45      if (mark->_pos < least_so_far)
      46        least_so_far = mark->_pos;
      47    return least_so_far;
      48  }
      49  libc_hidden_def (_IO_least_wmarker)
      50  
      51  /* Switch current get area from backup buffer to (start of) main get area. */
      52  void
      53  _IO_switch_to_main_wget_area (FILE *fp)
      54  {
      55    wchar_t *tmp;
      56    fp->_flags &= ~_IO_IN_BACKUP;
      57    /* Swap _IO_read_end and _IO_save_end. */
      58    tmp = fp->_wide_data->_IO_read_end;
      59    fp->_wide_data->_IO_read_end = fp->_wide_data->_IO_save_end;
      60    fp->_wide_data->_IO_save_end= tmp;
      61    /* Swap _IO_read_base and _IO_save_base. */
      62    tmp = fp->_wide_data->_IO_read_base;
      63    fp->_wide_data->_IO_read_base = fp->_wide_data->_IO_save_base;
      64    fp->_wide_data->_IO_save_base = tmp;
      65    /* Set _IO_read_ptr. */
      66    fp->_wide_data->_IO_read_ptr = fp->_wide_data->_IO_read_base;
      67  }
      68  libc_hidden_def (_IO_switch_to_main_wget_area)
      69  
      70  
      71  /* Switch current get area from main get area to (end of) backup area. */
      72  void
      73  _IO_switch_to_wbackup_area (FILE *fp)
      74  {
      75    wchar_t *tmp;
      76    fp->_flags |= _IO_IN_BACKUP;
      77    /* Swap _IO_read_end and _IO_save_end. */
      78    tmp = fp->_wide_data->_IO_read_end;
      79    fp->_wide_data->_IO_read_end = fp->_wide_data->_IO_save_end;
      80    fp->_wide_data->_IO_save_end = tmp;
      81    /* Swap _IO_read_base and _IO_save_base. */
      82    tmp = fp->_wide_data->_IO_read_base;
      83    fp->_wide_data->_IO_read_base = fp->_wide_data->_IO_save_base;
      84    fp->_wide_data->_IO_save_base = tmp;
      85    /* Set _IO_read_ptr.  */
      86    fp->_wide_data->_IO_read_ptr = fp->_wide_data->_IO_read_end;
      87  }
      88  libc_hidden_def (_IO_switch_to_wbackup_area)
      89  
      90  
      91  void
      92  _IO_wsetb (FILE *f, wchar_t *b, wchar_t *eb, int a)
      93  {
      94    if (f->_wide_data->_IO_buf_base && !(f->_flags2 & _IO_FLAGS2_USER_WBUF))
      95      free (f->_wide_data->_IO_buf_base);
      96    f->_wide_data->_IO_buf_base = b;
      97    f->_wide_data->_IO_buf_end = eb;
      98    if (a)
      99      f->_flags2 &= ~_IO_FLAGS2_USER_WBUF;
     100    else
     101      f->_flags2 |= _IO_FLAGS2_USER_WBUF;
     102  }
     103  libc_hidden_def (_IO_wsetb)
     104  
     105  
     106  wint_t
     107  _IO_wdefault_pbackfail (FILE *fp, wint_t c)
     108  {
     109    if (fp->_wide_data->_IO_read_ptr > fp->_wide_data->_IO_read_base
     110        && !_IO_in_backup (fp)
     111        && (wint_t) fp->_IO_read_ptr[-1] == c)
     112      --fp->_IO_read_ptr;
     113    else
     114      {
     115        /* Need to handle a filebuf in write mode (switch to read mode). FIXME!*/
     116        if (!_IO_in_backup (fp))
     117  	{
     118  	  /* We need to keep the invariant that the main get area
     119  	     logically follows the backup area.  */
     120  	  if (fp->_wide_data->_IO_read_ptr > fp->_wide_data->_IO_read_base
     121  	      && _IO_have_wbackup (fp))
     122  	    {
     123  	      if (save_for_wbackup (fp, fp->_wide_data->_IO_read_ptr))
     124  		return WEOF;
     125  	    }
     126  	  else if (!_IO_have_wbackup (fp))
     127  	    {
     128  	      /* No backup buffer: allocate one. */
     129  	      /* Use nshort buffer, if unused? (probably not)  FIXME */
     130  	      int backup_size = 128;
     131  	      wchar_t *bbuf = (wchar_t *) malloc (backup_size
     132  						  * sizeof (wchar_t));
     133  	      if (bbuf == NULL)
     134  		return WEOF;
     135  	      fp->_wide_data->_IO_save_base = bbuf;
     136  	      fp->_wide_data->_IO_save_end = (fp->_wide_data->_IO_save_base
     137  					      + backup_size);
     138  	      fp->_wide_data->_IO_backup_base = fp->_wide_data->_IO_save_end;
     139  	    }
     140  	  fp->_wide_data->_IO_read_base = fp->_wide_data->_IO_read_ptr;
     141  	  _IO_switch_to_wbackup_area (fp);
     142  	}
     143        else if (fp->_wide_data->_IO_read_ptr <= fp->_wide_data->_IO_read_base)
     144  	{
     145  	  /* Increase size of existing backup buffer. */
     146  	  size_t new_size;
     147  	  size_t old_size = (fp->_wide_data->_IO_read_end
     148                               - fp->_wide_data->_IO_read_base);
     149  	  wchar_t *new_buf;
     150  	  new_size = 2 * old_size;
     151  	  new_buf = (wchar_t *) malloc (new_size * sizeof (wchar_t));
     152  	  if (new_buf == NULL)
     153  	    return WEOF;
     154  	  __wmemcpy (new_buf + (new_size - old_size),
     155  		     fp->_wide_data->_IO_read_base, old_size);
     156  	  free (fp->_wide_data->_IO_read_base);
     157  	  _IO_wsetg (fp, new_buf, new_buf + (new_size - old_size),
     158  		     new_buf + new_size);
     159  	  fp->_wide_data->_IO_backup_base = fp->_wide_data->_IO_read_ptr;
     160  	}
     161  
     162        *--fp->_wide_data->_IO_read_ptr = c;
     163      }
     164    return c;
     165  }
     166  libc_hidden_def (_IO_wdefault_pbackfail)
     167  
     168  
     169  void
     170  _IO_wdefault_finish (FILE *fp, int dummy)
     171  {
     172    struct _IO_marker *mark;
     173    if (fp->_wide_data->_IO_buf_base && !(fp->_flags2 & _IO_FLAGS2_USER_WBUF))
     174      {
     175        free (fp->_wide_data->_IO_buf_base);
     176        fp->_wide_data->_IO_buf_base = fp->_wide_data->_IO_buf_end = NULL;
     177      }
     178  
     179    for (mark = fp->_markers; mark != NULL; mark = mark->_next)
     180      mark->_sbuf = NULL;
     181  
     182    if (fp->_IO_save_base)
     183      {
     184        free (fp->_wide_data->_IO_save_base);
     185        fp->_IO_save_base = NULL;
     186      }
     187  
     188  #ifdef _IO_MTSAFE_IO
     189    if (fp->_lock != NULL)
     190      _IO_lock_fini (*fp->_lock);
     191  #endif
     192  
     193    _IO_un_link ((struct _IO_FILE_plus *) fp);
     194  }
     195  libc_hidden_def (_IO_wdefault_finish)
     196  
     197  
     198  wint_t
     199  _IO_wdefault_uflow (FILE *fp)
     200  {
     201    wint_t wch;
     202    wch = _IO_UNDERFLOW (fp);
     203    if (wch == WEOF)
     204      return WEOF;
     205    return *fp->_wide_data->_IO_read_ptr++;
     206  }
     207  libc_hidden_def (_IO_wdefault_uflow)
     208  
     209  
     210  wint_t
     211  __woverflow (FILE *f, wint_t wch)
     212  {
     213    if (f->_mode == 0)
     214      _IO_fwide (f, 1);
     215    return _IO_OVERFLOW (f, wch);
     216  }
     217  libc_hidden_def (__woverflow)
     218  
     219  
     220  wint_t
     221  __wuflow (FILE *fp)
     222  {
     223    if (fp->_mode < 0 || (fp->_mode == 0 && _IO_fwide (fp, 1) != 1))
     224      return WEOF;
     225  
     226    if (fp->_mode == 0)
     227      _IO_fwide (fp, 1);
     228    if (_IO_in_put_mode (fp))
     229      if (_IO_switch_to_wget_mode (fp) == EOF)
     230        return WEOF;
     231    if (fp->_wide_data->_IO_read_ptr < fp->_wide_data->_IO_read_end)
     232      return *fp->_wide_data->_IO_read_ptr++;
     233    if (_IO_in_backup (fp))
     234      {
     235        _IO_switch_to_main_wget_area (fp);
     236        if (fp->_wide_data->_IO_read_ptr < fp->_wide_data->_IO_read_end)
     237  	return *fp->_wide_data->_IO_read_ptr++;
     238      }
     239    if (_IO_have_markers (fp))
     240      {
     241        if (save_for_wbackup (fp, fp->_wide_data->_IO_read_end))
     242  	return WEOF;
     243      }
     244    else if (_IO_have_wbackup (fp))
     245      _IO_free_wbackup_area (fp);
     246    return _IO_UFLOW (fp);
     247  }
     248  libc_hidden_def (__wuflow)
     249  
     250  wint_t
     251  __wunderflow (FILE *fp)
     252  {
     253    if (fp->_mode < 0 || (fp->_mode == 0 && _IO_fwide (fp, 1) != 1))
     254      return WEOF;
     255  
     256    if (fp->_mode == 0)
     257      _IO_fwide (fp, 1);
     258    if (_IO_in_put_mode (fp))
     259      if (_IO_switch_to_wget_mode (fp) == EOF)
     260        return WEOF;
     261    if (fp->_wide_data->_IO_read_ptr < fp->_wide_data->_IO_read_end)
     262      return *fp->_wide_data->_IO_read_ptr;
     263    if (_IO_in_backup (fp))
     264      {
     265        _IO_switch_to_main_wget_area (fp);
     266        if (fp->_wide_data->_IO_read_ptr < fp->_wide_data->_IO_read_end)
     267  	return *fp->_wide_data->_IO_read_ptr;
     268      }
     269    if (_IO_have_markers (fp))
     270      {
     271        if (save_for_wbackup (fp, fp->_wide_data->_IO_read_end))
     272  	return WEOF;
     273      }
     274    else if (_IO_have_backup (fp))
     275      _IO_free_wbackup_area (fp);
     276    return _IO_UNDERFLOW (fp);
     277  }
     278  libc_hidden_def (__wunderflow)
     279  
     280  
     281  size_t
     282  _IO_wdefault_xsputn (FILE *f, const void *data, size_t n)
     283  {
     284    const wchar_t *s = (const wchar_t *) data;
     285    size_t more = n;
     286    if (more <= 0)
     287      return 0;
     288    for (;;)
     289      {
     290        /* Space available. */
     291        ssize_t count = (f->_wide_data->_IO_write_end
     292                         - f->_wide_data->_IO_write_ptr);
     293        if (count > 0)
     294  	{
     295  	  if ((size_t) count > more)
     296  	    count = more;
     297  	  if (count > 20)
     298  	    {
     299  	      f->_wide_data->_IO_write_ptr =
     300  		__wmempcpy (f->_wide_data->_IO_write_ptr, s, count);
     301  	      s += count;
     302              }
     303  	  else if (count <= 0)
     304  	    count = 0;
     305  	  else
     306  	    {
     307  	      wchar_t *p = f->_wide_data->_IO_write_ptr;
     308  	      ssize_t i;
     309  	      for (i = count; --i >= 0; )
     310  		*p++ = *s++;
     311  	      f->_wide_data->_IO_write_ptr = p;
     312              }
     313  	  more -= count;
     314          }
     315        if (more == 0 || __woverflow (f, *s++) == WEOF)
     316  	break;
     317        more--;
     318      }
     319    return n - more;
     320  }
     321  libc_hidden_def (_IO_wdefault_xsputn)
     322  
     323  
     324  size_t
     325  _IO_wdefault_xsgetn (FILE *fp, void *data, size_t n)
     326  {
     327    size_t more = n;
     328    wchar_t *s = (wchar_t*) data;
     329    for (;;)
     330      {
     331        /* Data available. */
     332        ssize_t count = (fp->_wide_data->_IO_read_end
     333                         - fp->_wide_data->_IO_read_ptr);
     334        if (count > 0)
     335  	{
     336  	  if ((size_t) count > more)
     337  	    count = more;
     338  	  if (count > 20)
     339  	    {
     340  	      s = __wmempcpy (s, fp->_wide_data->_IO_read_ptr, count);
     341  	      fp->_wide_data->_IO_read_ptr += count;
     342  	    }
     343  	  else if (count <= 0)
     344  	    count = 0;
     345  	  else
     346  	    {
     347  	      wchar_t *p = fp->_wide_data->_IO_read_ptr;
     348  	      int i = (int) count;
     349  	      while (--i >= 0)
     350  		*s++ = *p++;
     351  	      fp->_wide_data->_IO_read_ptr = p;
     352              }
     353              more -= count;
     354          }
     355        if (more == 0 || __wunderflow (fp) == WEOF)
     356  	break;
     357      }
     358    return n - more;
     359  }
     360  libc_hidden_def (_IO_wdefault_xsgetn)
     361  
     362  
     363  void
     364  _IO_wdoallocbuf (FILE *fp)
     365  {
     366    if (fp->_wide_data->_IO_buf_base)
     367      return;
     368    if (!(fp->_flags & _IO_UNBUFFERED))
     369      if ((wint_t)_IO_WDOALLOCATE (fp) != WEOF)
     370        return;
     371    _IO_wsetb (fp, fp->_wide_data->_shortbuf,
     372  		     fp->_wide_data->_shortbuf + 1, 0);
     373  }
     374  libc_hidden_def (_IO_wdoallocbuf)
     375  
     376  
     377  int
     378  _IO_wdefault_doallocate (FILE *fp)
     379  {
     380    wchar_t *buf = (wchar_t *)malloc (BUFSIZ);
     381    if (__glibc_unlikely (buf == NULL))
     382      return EOF;
     383  
     384    _IO_wsetb (fp, buf, buf + BUFSIZ / sizeof *buf, 1);
     385    return 1;
     386  }
     387  libc_hidden_def (_IO_wdefault_doallocate)
     388  
     389  
     390  int
     391  _IO_switch_to_wget_mode (FILE *fp)
     392  {
     393    if (fp->_wide_data->_IO_write_ptr > fp->_wide_data->_IO_write_base)
     394      if ((wint_t)_IO_WOVERFLOW (fp, WEOF) == WEOF)
     395        return EOF;
     396    if (_IO_in_backup (fp))
     397      fp->_wide_data->_IO_read_base = fp->_wide_data->_IO_backup_base;
     398    else
     399      {
     400        fp->_wide_data->_IO_read_base = fp->_wide_data->_IO_buf_base;
     401        if (fp->_wide_data->_IO_write_ptr > fp->_wide_data->_IO_read_end)
     402  	fp->_wide_data->_IO_read_end = fp->_wide_data->_IO_write_ptr;
     403      }
     404    fp->_wide_data->_IO_read_ptr = fp->_wide_data->_IO_write_ptr;
     405  
     406    fp->_wide_data->_IO_write_base = fp->_wide_data->_IO_write_ptr
     407      = fp->_wide_data->_IO_write_end = fp->_wide_data->_IO_read_ptr;
     408  
     409    fp->_flags &= ~_IO_CURRENTLY_PUTTING;
     410    return 0;
     411  }
     412  libc_hidden_def (_IO_switch_to_wget_mode)
     413  
     414  void
     415  _IO_free_wbackup_area (FILE *fp)
     416  {
     417    if (_IO_in_backup (fp))
     418      _IO_switch_to_main_wget_area (fp);  /* Just in case. */
     419    free (fp->_wide_data->_IO_save_base);
     420    fp->_wide_data->_IO_save_base = NULL;
     421    fp->_wide_data->_IO_save_end = NULL;
     422    fp->_wide_data->_IO_backup_base = NULL;
     423  }
     424  libc_hidden_def (_IO_free_wbackup_area)
     425  
     426  static int
     427  save_for_wbackup (FILE *fp, wchar_t *end_p)
     428  {
     429    /* Append [_IO_read_base..end_p] to backup area. */
     430    ssize_t least_mark = _IO_least_wmarker (fp, end_p);
     431    /* needed_size is how much space we need in the backup area. */
     432    size_t needed_size = ((end_p - fp->_wide_data->_IO_read_base)
     433                          - least_mark);
     434    /* FIXME: Dubious arithmetic if pointers are NULL */
     435    size_t current_Bsize = (fp->_wide_data->_IO_save_end
     436                            - fp->_wide_data->_IO_save_base);
     437    size_t avail; /* Extra space available for future expansion. */
     438    ssize_t delta;
     439    struct _IO_marker *mark;
     440    if (needed_size > current_Bsize)
     441      {
     442        wchar_t *new_buffer;
     443        avail = 100;
     444        new_buffer = (wchar_t *) malloc ((avail + needed_size)
     445  				       * sizeof (wchar_t));
     446        if (new_buffer == NULL)
     447  	return EOF;		/* FIXME */
     448        if (least_mark < 0)
     449  	{
     450  	  __wmempcpy (__wmempcpy (new_buffer + avail,
     451  				  fp->_wide_data->_IO_save_end + least_mark,
     452  				  -least_mark),
     453  		      fp->_wide_data->_IO_read_base,
     454  		      end_p - fp->_wide_data->_IO_read_base);
     455  	}
     456        else
     457  	{
     458  	  __wmemcpy (new_buffer + avail,
     459  		     fp->_wide_data->_IO_read_base + least_mark,
     460  		     needed_size);
     461  	}
     462        free (fp->_wide_data->_IO_save_base);
     463        fp->_wide_data->_IO_save_base = new_buffer;
     464        fp->_wide_data->_IO_save_end = new_buffer + avail + needed_size;
     465      }
     466    else
     467      {
     468        avail = current_Bsize - needed_size;
     469        if (least_mark < 0)
     470  	{
     471  	  __wmemmove (fp->_wide_data->_IO_save_base + avail,
     472  		      fp->_wide_data->_IO_save_end + least_mark,
     473  		      -least_mark);
     474  	  __wmemcpy (fp->_wide_data->_IO_save_base + avail - least_mark,
     475  		     fp->_wide_data->_IO_read_base,
     476  		     end_p - fp->_wide_data->_IO_read_base);
     477  	}
     478        else if (needed_size > 0)
     479  	__wmemcpy (fp->_wide_data->_IO_save_base + avail,
     480  		   fp->_wide_data->_IO_read_base + least_mark,
     481  		   needed_size);
     482      }
     483    fp->_wide_data->_IO_backup_base = fp->_wide_data->_IO_save_base + avail;
     484    /* Adjust all the streammarkers. */
     485    delta = end_p - fp->_wide_data->_IO_read_base;
     486    for (mark = fp->_markers; mark != NULL; mark = mark->_next)
     487      mark->_pos -= delta;
     488    return 0;
     489  }
     490  
     491  wint_t
     492  _IO_sputbackwc (FILE *fp, wint_t c)
     493  {
     494    wint_t result;
     495  
     496    if (fp->_wide_data->_IO_read_ptr > fp->_wide_data->_IO_read_base
     497        && (wchar_t)fp->_wide_data->_IO_read_ptr[-1] == (wchar_t) c)
     498      {
     499        fp->_wide_data->_IO_read_ptr--;
     500        result = c;
     501      }
     502    else
     503      result = _IO_PBACKFAIL (fp, c);
     504  
     505    if (result != WEOF)
     506      fp->_flags &= ~_IO_EOF_SEEN;
     507  
     508    return result;
     509  }
     510  libc_hidden_def (_IO_sputbackwc)
     511  
     512  wint_t
     513  _IO_sungetwc (FILE *fp)
     514  {
     515    wint_t result;
     516  
     517    if (fp->_wide_data->_IO_read_ptr > fp->_wide_data->_IO_read_base)
     518      {
     519        fp->_wide_data->_IO_read_ptr--;
     520        result = *fp->_wide_data->_IO_read_ptr;
     521      }
     522    else
     523      result = _IO_PBACKFAIL (fp, EOF);
     524  
     525    if (result != WEOF)
     526      fp->_flags &= ~_IO_EOF_SEEN;
     527  
     528    return result;
     529  }
     530  
     531  
     532  unsigned
     533  _IO_adjust_wcolumn (unsigned start, const wchar_t *line, int count)
     534  {
     535    const wchar_t *ptr = line + count;
     536    while (ptr > line)
     537      if (*--ptr == L'\n')
     538        return line + count - ptr - 1;
     539    return start + count;
     540  }
     541  
     542  void
     543  _IO_init_wmarker (struct _IO_marker *marker, FILE *fp)
     544  {
     545    marker->_sbuf = fp;
     546    if (_IO_in_put_mode (fp))
     547      _IO_switch_to_wget_mode (fp);
     548    if (_IO_in_backup (fp))
     549      marker->_pos = fp->_wide_data->_IO_read_ptr - fp->_wide_data->_IO_read_end;
     550    else
     551      marker->_pos = (fp->_wide_data->_IO_read_ptr
     552  		    - fp->_wide_data->_IO_read_base);
     553  
     554    /* Should perhaps sort the chain? */
     555    marker->_next = fp->_markers;
     556    fp->_markers = marker;
     557  }
     558  
     559  #define BAD_DELTA EOF
     560  
     561  /* Return difference between MARK and current position of MARK's stream. */
     562  int
     563  _IO_wmarker_delta (struct _IO_marker *mark)
     564  {
     565    int cur_pos;
     566    if (mark->_sbuf == NULL)
     567      return BAD_DELTA;
     568    if (_IO_in_backup (mark->_sbuf))
     569      cur_pos = (mark->_sbuf->_wide_data->_IO_read_ptr
     570  	       - mark->_sbuf->_wide_data->_IO_read_end);
     571    else
     572      cur_pos = (mark->_sbuf->_wide_data->_IO_read_ptr
     573  	       - mark->_sbuf->_wide_data->_IO_read_base);
     574    return mark->_pos - cur_pos;
     575  }
     576  
     577  int
     578  _IO_seekwmark (FILE *fp, struct _IO_marker *mark, int delta)
     579  {
     580    if (mark->_sbuf != fp)
     581      return EOF;
     582   if (mark->_pos >= 0)
     583      {
     584        if (_IO_in_backup (fp))
     585  	_IO_switch_to_main_wget_area (fp);
     586        fp->_wide_data->_IO_read_ptr = (fp->_wide_data->_IO_read_base
     587  				      + mark->_pos);
     588      }
     589    else
     590      {
     591        if (!_IO_in_backup (fp))
     592  	_IO_switch_to_wbackup_area (fp);
     593        fp->_wide_data->_IO_read_ptr = fp->_wide_data->_IO_read_end + mark->_pos;
     594      }
     595    return 0;
     596  }
     597  
     598  void
     599  _IO_unsave_wmarkers (FILE *fp)
     600  {
     601    struct _IO_marker *mark = fp->_markers;
     602    if (mark)
     603      {
     604        fp->_markers = 0;
     605      }
     606  
     607    if (_IO_have_backup (fp))
     608      _IO_free_wbackup_area (fp);
     609  }