Back to index

glibc  2.9
wgenops.c
Go to the documentation of this file.
00001 /* Copyright (C) 1993,1995,1997-2002,2004,2006 Free Software Foundation, Inc.
00002    This file is part of the GNU C Library.
00003    Written by Ulrich Drepper <drepper@cygnus.com>.
00004    Based on the single byte version by Per Bothner <bothner@cygnus.com>.
00005 
00006    The GNU C Library is free software; you can redistribute it and/or
00007    modify it under the terms of the GNU Lesser General Public
00008    License as published by the Free Software Foundation; either
00009    version 2.1 of the License, or (at your option) any later version.
00010 
00011    The GNU C Library is distributed in the hope that it will be useful,
00012    but WITHOUT ANY WARRANTY; without even the implied warranty of
00013    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
00014    Lesser General Public License for more details.
00015 
00016    You should have received a copy of the GNU Lesser General Public
00017    License along with the GNU C Library; if not, write to the Free
00018    Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA
00019    02111-1307 USA.
00020 
00021    As a special exception, if you link the code in this file with
00022    files compiled with a GNU compiler to produce an executable,
00023    that does not cause the resulting executable to be covered by
00024    the GNU Lesser General Public License.  This exception does not
00025    however invalidate any other reasons why the executable file
00026    might be covered by the GNU Lesser General Public License.
00027    This exception applies to code released by its copyright holders
00028    in files containing the exception.  */
00029 
00030 /* Generic or default I/O operations. */
00031 
00032 #include "libioP.h"
00033 #ifdef __STDC__
00034 #include <stdlib.h>
00035 #endif
00036 #include <string.h>
00037 #include <wchar.h>
00038 
00039 
00040 #ifndef _LIBC
00041 # define __wmemcpy(dst, src, n) wmemcpy (dst, src, n)
00042 #endif
00043 
00044 
00045 static int save_for_wbackup (_IO_FILE *fp, wchar_t *end_p) __THROW
00046 #ifdef _LIBC
00047      internal_function
00048 #endif
00049      ;
00050 
00051 /* Return minimum _pos markers
00052    Assumes the current get area is the main get area. */
00053 _IO_ssize_t _IO_least_wmarker (_IO_FILE *fp, wchar_t *end_p) __THROW;
00054 
00055 _IO_ssize_t
00056 _IO_least_wmarker (fp, end_p)
00057      _IO_FILE *fp;
00058      wchar_t *end_p;
00059 {
00060   _IO_ssize_t least_so_far = end_p - fp->_wide_data->_IO_read_base;
00061   struct _IO_marker *mark;
00062   for (mark = fp->_markers; mark != NULL; mark = mark->_next)
00063     if (mark->_pos < least_so_far)
00064       least_so_far = mark->_pos;
00065   return least_so_far;
00066 }
00067 INTDEF(_IO_least_wmarker)
00068 
00069 /* Switch current get area from backup buffer to (start of) main get area. */
00070 void
00071 _IO_switch_to_main_wget_area (fp)
00072      _IO_FILE *fp;
00073 {
00074   wchar_t *tmp;
00075   fp->_flags &= ~_IO_IN_BACKUP;
00076   /* Swap _IO_read_end and _IO_save_end. */
00077   tmp = fp->_wide_data->_IO_read_end;
00078   fp->_wide_data->_IO_read_end = fp->_wide_data->_IO_save_end;
00079   fp->_wide_data->_IO_save_end= tmp;
00080   /* Swap _IO_read_base and _IO_save_base. */
00081   tmp = fp->_wide_data->_IO_read_base;
00082   fp->_wide_data->_IO_read_base = fp->_wide_data->_IO_save_base;
00083   fp->_wide_data->_IO_save_base = tmp;
00084   /* Set _IO_read_ptr. */
00085   fp->_wide_data->_IO_read_ptr = fp->_wide_data->_IO_read_base;
00086 }
00087 INTDEF(_IO_switch_to_main_wget_area)
00088 
00089 
00090 /* Switch current get area from main get area to (end of) backup area. */
00091 void
00092 _IO_switch_to_wbackup_area (fp)
00093      _IO_FILE *fp;
00094 {
00095   wchar_t *tmp;
00096   fp->_flags |= _IO_IN_BACKUP;
00097   /* Swap _IO_read_end and _IO_save_end. */
00098   tmp = fp->_wide_data->_IO_read_end;
00099   fp->_wide_data->_IO_read_end = fp->_wide_data->_IO_save_end;
00100   fp->_wide_data->_IO_save_end = tmp;
00101   /* Swap _IO_read_base and _IO_save_base. */
00102   tmp = fp->_wide_data->_IO_read_base;
00103   fp->_wide_data->_IO_read_base = fp->_wide_data->_IO_save_base;
00104   fp->_wide_data->_IO_save_base = tmp;
00105   /* Set _IO_read_ptr.  */
00106   fp->_wide_data->_IO_read_ptr = fp->_wide_data->_IO_read_end;
00107 }
00108 INTDEF(_IO_switch_to_wbackup_area)
00109 
00110 
00111 void
00112 _IO_wsetb (f, b, eb, a)
00113      _IO_FILE *f;
00114      wchar_t *b;
00115      wchar_t *eb;
00116      int a;
00117 {
00118   if (f->_wide_data->_IO_buf_base && !(f->_flags2 & _IO_FLAGS2_USER_WBUF))
00119     FREE_BUF (f->_wide_data->_IO_buf_base, _IO_wblen (f) * sizeof (wchar_t));
00120   f->_wide_data->_IO_buf_base = b;
00121   f->_wide_data->_IO_buf_end = eb;
00122   if (a)
00123     f->_flags2 &= ~_IO_FLAGS2_USER_WBUF;
00124   else
00125     f->_flags2 |= _IO_FLAGS2_USER_WBUF;
00126 }
00127 INTDEF(_IO_wsetb)
00128 
00129 
00130 wint_t
00131 _IO_wdefault_pbackfail (fp, c)
00132      _IO_FILE *fp;
00133      wint_t c;
00134 {
00135   if (fp->_wide_data->_IO_read_ptr > fp->_wide_data->_IO_read_base
00136       && !_IO_in_backup (fp)
00137       && (wint_t) fp->_IO_read_ptr[-1] == c)
00138     --fp->_IO_read_ptr;
00139   else
00140     {
00141       /* Need to handle a filebuf in write mode (switch to read mode). FIXME!*/
00142       if (!_IO_in_backup (fp))
00143        {
00144          /* We need to keep the invariant that the main get area
00145             logically follows the backup area.  */
00146          if (fp->_wide_data->_IO_read_ptr > fp->_wide_data->_IO_read_base
00147              && _IO_have_wbackup (fp))
00148            {
00149              if (save_for_wbackup (fp, fp->_wide_data->_IO_read_ptr))
00150               return WEOF;
00151            }
00152          else if (!_IO_have_wbackup (fp))
00153            {
00154              /* No backup buffer: allocate one. */
00155              /* Use nshort buffer, if unused? (probably not)  FIXME */
00156              int backup_size = 128;
00157              wchar_t *bbuf = (wchar_t *) malloc (backup_size
00158                                             * sizeof (wchar_t));
00159              if (bbuf == NULL)
00160               return WEOF;
00161              fp->_wide_data->_IO_save_base = bbuf;
00162              fp->_wide_data->_IO_save_end = (fp->_wide_data->_IO_save_base
00163                                          + backup_size);
00164              fp->_wide_data->_IO_backup_base = fp->_wide_data->_IO_save_end;
00165            }
00166          fp->_wide_data->_IO_read_base = fp->_wide_data->_IO_read_ptr;
00167          INTUSE(_IO_switch_to_wbackup_area) (fp);
00168        }
00169       else if (fp->_wide_data->_IO_read_ptr <= fp->_wide_data->_IO_read_base)
00170        {
00171          /* Increase size of existing backup buffer. */
00172          _IO_size_t new_size;
00173          _IO_size_t old_size = (fp->_wide_data->_IO_read_end
00174                              - fp->_wide_data->_IO_read_base);
00175          wchar_t *new_buf;
00176          new_size = 2 * old_size;
00177          new_buf = (wchar_t *) malloc (new_size * sizeof (wchar_t));
00178          if (new_buf == NULL)
00179            return WEOF;
00180          __wmemcpy (new_buf + (new_size - old_size),
00181                    fp->_wide_data->_IO_read_base, old_size);
00182          free (fp->_wide_data->_IO_read_base);
00183          _IO_wsetg (fp, new_buf, new_buf + (new_size - old_size),
00184                    new_buf + new_size);
00185          fp->_wide_data->_IO_backup_base = fp->_wide_data->_IO_read_ptr;
00186        }
00187 
00188       *--fp->_wide_data->_IO_read_ptr = c;
00189     }
00190   return c;
00191 }
00192 INTDEF(_IO_wdefault_pbackfail)
00193 
00194 
00195 void
00196 _IO_wdefault_finish (fp, dummy)
00197      _IO_FILE *fp;
00198      int dummy;
00199 {
00200   struct _IO_marker *mark;
00201   if (fp->_wide_data->_IO_buf_base && !(fp->_flags2 & _IO_FLAGS2_USER_WBUF))
00202     {
00203       FREE_BUF (fp->_wide_data->_IO_buf_base,
00204               _IO_wblen (fp) * sizeof (wchar_t));
00205       fp->_wide_data->_IO_buf_base = fp->_wide_data->_IO_buf_end = NULL;
00206     }
00207 
00208   for (mark = fp->_markers; mark != NULL; mark = mark->_next)
00209     mark->_sbuf = NULL;
00210 
00211   if (fp->_IO_save_base)
00212     {
00213       free (fp->_wide_data->_IO_save_base);
00214       fp->_IO_save_base = NULL;
00215     }
00216 
00217 #ifdef _IO_MTSAFE_IO
00218   if (fp->_lock != NULL)
00219     _IO_lock_fini (*fp->_lock);
00220 #endif
00221 
00222   INTUSE(_IO_un_link) ((struct _IO_FILE_plus *) fp);
00223 }
00224 INTDEF(_IO_wdefault_finish)
00225 
00226 
00227 wint_t
00228 _IO_wdefault_uflow (fp)
00229      _IO_FILE *fp;
00230 {
00231   wint_t wch;
00232   wch = _IO_UNDERFLOW (fp);
00233   if (wch == WEOF)
00234     return WEOF;
00235   return *fp->_wide_data->_IO_read_ptr++;
00236 }
00237 INTDEF(_IO_wdefault_uflow)
00238 
00239 
00240 wint_t
00241 __woverflow (f, wch)
00242      _IO_FILE *f;
00243      wint_t wch;
00244 {
00245   if (f->_mode == 0)
00246     _IO_fwide (f, 1);
00247   return _IO_OVERFLOW (f, wch);
00248 }
00249 libc_hidden_def (__woverflow)
00250 
00251 
00252 wint_t
00253 __wuflow (fp)
00254      _IO_FILE *fp;
00255 {
00256   if (fp->_mode < 0 || (fp->_mode == 0 && _IO_fwide (fp, 1) != 1))
00257     return WEOF;
00258 
00259   if (fp->_mode == 0)
00260     _IO_fwide (fp, 1);
00261   if (_IO_in_put_mode (fp))
00262     if (INTUSE(_IO_switch_to_wget_mode) (fp) == EOF)
00263       return WEOF;
00264   if (fp->_wide_data->_IO_read_ptr < fp->_wide_data->_IO_read_end)
00265     return *fp->_wide_data->_IO_read_ptr++;
00266   if (_IO_in_backup (fp))
00267     {
00268       INTUSE(_IO_switch_to_main_wget_area) (fp);
00269       if (fp->_wide_data->_IO_read_ptr < fp->_wide_data->_IO_read_end)
00270        return *fp->_wide_data->_IO_read_ptr++;
00271     }
00272   if (_IO_have_markers (fp))
00273     {
00274       if (save_for_wbackup (fp, fp->_wide_data->_IO_read_end))
00275        return WEOF;
00276     }
00277   else if (_IO_have_wbackup (fp))
00278     INTUSE(_IO_free_wbackup_area) (fp);
00279   return _IO_UFLOW (fp);
00280 }
00281 libc_hidden_def (__wuflow)
00282 
00283 wint_t
00284 __wunderflow (fp)
00285      _IO_FILE *fp;
00286 {
00287   if (fp->_mode < 0 || (fp->_mode == 0 && _IO_fwide (fp, 1) != 1))
00288     return WEOF;
00289 
00290   if (fp->_mode == 0)
00291     _IO_fwide (fp, 1);
00292   if (_IO_in_put_mode (fp))
00293     if (INTUSE(_IO_switch_to_wget_mode) (fp) == EOF)
00294       return WEOF;
00295   if (fp->_wide_data->_IO_read_ptr < fp->_wide_data->_IO_read_end)
00296     return *fp->_wide_data->_IO_read_ptr;
00297   if (_IO_in_backup (fp))
00298     {
00299       INTUSE(_IO_switch_to_main_wget_area) (fp);
00300       if (fp->_wide_data->_IO_read_ptr < fp->_wide_data->_IO_read_end)
00301        return *fp->_wide_data->_IO_read_ptr;
00302     }
00303   if (_IO_have_markers (fp))
00304     {
00305       if (save_for_wbackup (fp, fp->_wide_data->_IO_read_end))
00306        return WEOF;
00307     }
00308   else if (_IO_have_backup (fp))
00309     INTUSE(_IO_free_wbackup_area) (fp);
00310   return _IO_UNDERFLOW (fp);
00311 }
00312 libc_hidden_def (__wunderflow)
00313 
00314 
00315 _IO_size_t
00316 _IO_wdefault_xsputn (f, data, n)
00317      _IO_FILE *f;
00318      const void *data;
00319      _IO_size_t n;
00320 {
00321   const wchar_t *s = (const wchar_t *) data;
00322   _IO_size_t more = n;
00323   if (more <= 0)
00324     return 0;
00325   for (;;)
00326     {
00327       /* Space available. */
00328       _IO_ssize_t count = (f->_wide_data->_IO_write_end
00329                         - f->_wide_data->_IO_write_ptr);
00330       if (count > 0)
00331        {
00332          if ((_IO_size_t) count > more)
00333            count = more;
00334          if (count > 20)
00335            {
00336 #ifdef _LIBC
00337              f->_wide_data->_IO_write_ptr =
00338               __wmempcpy (f->_wide_data->_IO_write_ptr, s, count);
00339 #else
00340              memcpy (f->_wide_data->_IO_write_ptr, s, count);
00341              f->_wide_data->_IO_write_ptr += count;
00342 #endif
00343              s += count;
00344             }
00345          else if (count <= 0)
00346            count = 0;
00347          else
00348            {
00349              wchar_t *p = f->_wide_data->_IO_write_ptr;
00350              _IO_ssize_t i;
00351              for (i = count; --i >= 0; )
00352               *p++ = *s++;
00353              f->_wide_data->_IO_write_ptr = p;
00354             }
00355          more -= count;
00356         }
00357       if (more == 0 || __woverflow (f, *s++) == WEOF)
00358        break;
00359       more--;
00360     }
00361   return n - more;
00362 }
00363 INTDEF(_IO_wdefault_xsputn)
00364 
00365 
00366 _IO_size_t
00367 _IO_wdefault_xsgetn (fp, data, n)
00368      _IO_FILE *fp;
00369      void *data;
00370      _IO_size_t n;
00371 {
00372   _IO_size_t more = n;
00373   wchar_t *s = (wchar_t*) data;
00374   for (;;)
00375     {
00376       /* Data available. */
00377       _IO_ssize_t count = (fp->_wide_data->_IO_read_end
00378                         - fp->_wide_data->_IO_read_ptr);
00379       if (count > 0)
00380        {
00381          if ((_IO_size_t) count > more)
00382            count = more;
00383          if (count > 20)
00384            {
00385 #ifdef _LIBC
00386              s = __wmempcpy (s, fp->_wide_data->_IO_read_ptr, count);
00387 #else
00388              memcpy (s, fp->_wide_data->_IO_read_ptr, count);
00389              s += count;
00390 #endif
00391              fp->_wide_data->_IO_read_ptr += count;
00392            }
00393          else if (count <= 0)
00394            count = 0;
00395          else
00396            {
00397              wchar_t *p = fp->_wide_data->_IO_read_ptr;
00398              int i = (int) count;
00399              while (--i >= 0)
00400               *s++ = *p++;
00401              fp->_wide_data->_IO_read_ptr = p;
00402             }
00403             more -= count;
00404         }
00405       if (more == 0 || __wunderflow (fp) == WEOF)
00406        break;
00407     }
00408   return n - more;
00409 }
00410 INTDEF(_IO_wdefault_xsgetn)
00411 
00412 
00413 void
00414 _IO_wdoallocbuf (fp)
00415      _IO_FILE *fp;
00416 {
00417   if (fp->_wide_data->_IO_buf_base)
00418     return;
00419   if (!(fp->_flags & _IO_UNBUFFERED))
00420     if ((wint_t)_IO_WDOALLOCATE (fp) != WEOF)
00421       return;
00422   INTUSE(_IO_wsetb) (fp, fp->_wide_data->_shortbuf,
00423                    fp->_wide_data->_shortbuf + 1, 0);
00424 }
00425 INTDEF(_IO_wdoallocbuf)
00426 
00427 
00428 int
00429 _IO_wdefault_doallocate (fp)
00430      _IO_FILE *fp;
00431 {
00432   wchar_t *buf;
00433 
00434   ALLOC_WBUF (buf, _IO_BUFSIZ, EOF);
00435   INTUSE(_IO_wsetb) (fp, buf, buf + _IO_BUFSIZ, 1);
00436   return 1;
00437 }
00438 INTDEF(_IO_wdefault_doallocate)
00439 
00440 
00441 int
00442 _IO_switch_to_wget_mode (fp)
00443      _IO_FILE *fp;
00444 {
00445   if (fp->_wide_data->_IO_write_ptr > fp->_wide_data->_IO_write_base)
00446     if ((wint_t)_IO_WOVERFLOW (fp, WEOF) == WEOF)
00447       return EOF;
00448   if (_IO_in_backup (fp))
00449     fp->_wide_data->_IO_read_base = fp->_wide_data->_IO_backup_base;
00450   else
00451     {
00452       fp->_wide_data->_IO_read_base = fp->_wide_data->_IO_buf_base;
00453       if (fp->_wide_data->_IO_write_ptr > fp->_wide_data->_IO_read_end)
00454        fp->_wide_data->_IO_read_end = fp->_wide_data->_IO_write_ptr;
00455     }
00456   fp->_wide_data->_IO_read_ptr = fp->_wide_data->_IO_write_ptr;
00457 
00458   fp->_wide_data->_IO_write_base = fp->_wide_data->_IO_write_ptr
00459     = fp->_wide_data->_IO_write_end = fp->_wide_data->_IO_read_ptr;
00460 
00461   fp->_flags &= ~_IO_CURRENTLY_PUTTING;
00462   return 0;
00463 }
00464 INTDEF(_IO_switch_to_wget_mode)
00465 
00466 void
00467 _IO_free_wbackup_area (fp)
00468      _IO_FILE *fp;
00469 {
00470   if (_IO_in_backup (fp))
00471     INTUSE(_IO_switch_to_main_wget_area) (fp);  /* Just in case. */
00472   free (fp->_wide_data->_IO_save_base);
00473   fp->_wide_data->_IO_save_base = NULL;
00474   fp->_wide_data->_IO_save_end = NULL;
00475   fp->_wide_data->_IO_backup_base = NULL;
00476 }
00477 INTDEF(_IO_free_wbackup_area)
00478 
00479 #if 0
00480 int
00481 _IO_switch_to_wput_mode (fp)
00482      _IO_FILE *fp;
00483 {
00484   fp->_wide_data->_IO_write_base = fp->_wide_data->_IO_read_ptr;
00485   fp->_wide_data->_IO_write_ptr = fp->_wide_data->_IO_read_ptr;
00486   /* Following is wrong if line- or un-buffered? */
00487   fp->_wide_data->_IO_write_end = (fp->_flags & _IO_IN_BACKUP
00488                                ? fp->_wide_data->_IO_read_end
00489                                : fp->_wide_data->_IO_buf_end);
00490 
00491   fp->_wide_data->_IO_read_ptr = fp->_wide_data->_IO_read_end;
00492   fp->_wide_data->_IO_read_base = fp->_wide_data->_IO_read_end;
00493 
00494   fp->_flags |= _IO_CURRENTLY_PUTTING;
00495   return 0;
00496 }
00497 #endif
00498 
00499 
00500 static int
00501 #ifdef _LIBC
00502 internal_function
00503 #endif
00504 save_for_wbackup (fp, end_p)
00505      _IO_FILE *fp;
00506      wchar_t *end_p;
00507 {
00508   /* Append [_IO_read_base..end_p] to backup area. */
00509   _IO_ssize_t least_mark = INTUSE(_IO_least_wmarker) (fp, end_p);
00510   /* needed_size is how much space we need in the backup area. */
00511   _IO_size_t needed_size = ((end_p - fp->_wide_data->_IO_read_base)
00512                          - least_mark);
00513   /* FIXME: Dubious arithmetic if pointers are NULL */
00514   _IO_size_t current_Bsize = (fp->_wide_data->_IO_save_end
00515                            - fp->_wide_data->_IO_save_base);
00516   _IO_size_t avail; /* Extra space available for future expansion. */
00517   _IO_ssize_t delta;
00518   struct _IO_marker *mark;
00519   if (needed_size > current_Bsize)
00520     {
00521       wchar_t *new_buffer;
00522       avail = 100;
00523       new_buffer = (wchar_t *) malloc ((avail + needed_size)
00524                                    * sizeof (wchar_t));
00525       if (new_buffer == NULL)
00526        return EOF;          /* FIXME */
00527       if (least_mark < 0)
00528        {
00529 #ifdef _LIBC
00530          __wmempcpy (__wmempcpy (new_buffer + avail,
00531                               fp->_wide_data->_IO_save_end + least_mark,
00532                               -least_mark),
00533                     fp->_wide_data->_IO_read_base,
00534                     end_p - fp->_wide_data->_IO_read_base);
00535 #else
00536          memcpy (new_buffer + avail,
00537                 fp->_wide_data->_IO_save_end + least_mark,
00538                 -least_mark * sizeof (wchar_t));
00539          memcpy (new_buffer + avail - least_mark,
00540                 fp->_wide_data->_IO_read_base,
00541                 (end_p - fp->_wide_data->_IO_read_base) * sizeof (wchar_t));
00542 #endif
00543        }
00544       else
00545        {
00546 #ifdef _LIBC
00547          __wmemcpy (new_buffer + avail,
00548                    fp->_wide_data->_IO_read_base + least_mark,
00549                    needed_size);
00550 #else
00551          memcpy (new_buffer + avail,
00552                 fp->_wide_data->_IO_read_base + least_mark,
00553                 needed_size * sizeof (wchar_t));
00554 #endif
00555        }
00556       free (fp->_wide_data->_IO_save_base);
00557       fp->_wide_data->_IO_save_base = new_buffer;
00558       fp->_wide_data->_IO_save_end = new_buffer + avail + needed_size;
00559     }
00560   else
00561     {
00562       avail = current_Bsize - needed_size;
00563       if (least_mark < 0)
00564        {
00565 #ifdef _LIBC
00566          __wmemmove (fp->_wide_data->_IO_save_base + avail,
00567                     fp->_wide_data->_IO_save_end + least_mark,
00568                     -least_mark);
00569          __wmemcpy (fp->_wide_data->_IO_save_base + avail - least_mark,
00570                    fp->_wide_data->_IO_read_base,
00571                    end_p - fp->_wide_data->_IO_read_base);
00572 #else
00573          memmove (fp->_wide_data->_IO_save_base + avail,
00574                  fp->_wide_data->_IO_save_end + least_mark,
00575                  -least_mark * sizeof (wchar_t));
00576          memcpy (fp->_wide_data->_IO_save_base + avail - least_mark,
00577                 fp->_wide_data->_IO_read_base,
00578                 (end_p - fp->_wide_data->_IO_read_base) * sizeof (wchar_t));
00579 #endif
00580        }
00581       else if (needed_size > 0)
00582 #ifdef _LIBC
00583        __wmemcpy (fp->_wide_data->_IO_save_base + avail,
00584                  fp->_wide_data->_IO_read_base + least_mark,
00585                  needed_size);
00586 #else
00587        memcpy (fp->_wide_data->_IO_save_base + avail,
00588               fp->_wide_data->_IO_read_base + least_mark,
00589               needed_size * sizeof (wchar_t));
00590 #endif
00591     }
00592   fp->_wide_data->_IO_backup_base = fp->_wide_data->_IO_save_base + avail;
00593   /* Adjust all the streammarkers. */
00594   delta = end_p - fp->_wide_data->_IO_read_base;
00595   for (mark = fp->_markers; mark != NULL; mark = mark->_next)
00596     mark->_pos -= delta;
00597   return 0;
00598 }
00599 
00600 wint_t
00601 _IO_sputbackwc (fp, c)
00602      _IO_FILE *fp;
00603      wint_t c;
00604 {
00605   wint_t result;
00606 
00607   if (fp->_wide_data->_IO_read_ptr > fp->_wide_data->_IO_read_base
00608       && (wchar_t)fp->_wide_data->_IO_read_ptr[-1] == (wchar_t) c)
00609     {
00610       fp->_wide_data->_IO_read_ptr--;
00611       result = c;
00612     }
00613   else
00614     result = _IO_PBACKFAIL (fp, c);
00615 
00616   if (result != WEOF)
00617     fp->_flags &= ~_IO_EOF_SEEN;
00618 
00619   return result;
00620 }
00621 INTDEF(_IO_sputbackwc)
00622 
00623 wint_t
00624 _IO_sungetwc (fp)
00625      _IO_FILE *fp;
00626 {
00627   wint_t result;
00628 
00629   if (fp->_wide_data->_IO_read_ptr > fp->_wide_data->_IO_read_base)
00630     {
00631       fp->_wide_data->_IO_read_ptr--;
00632       result = *fp->_wide_data->_IO_read_ptr;
00633     }
00634   else
00635     result = _IO_PBACKFAIL (fp, EOF);
00636 
00637   if (result != WEOF)
00638     fp->_flags &= ~_IO_EOF_SEEN;
00639 
00640   return result;
00641 }
00642 
00643 
00644 unsigned
00645 _IO_adjust_wcolumn (start, line, count)
00646      unsigned start;
00647      const wchar_t *line;
00648      int count;
00649 {
00650   const wchar_t *ptr = line + count;
00651   while (ptr > line)
00652     if (*--ptr == L'\n')
00653       return line + count - ptr - 1;
00654   return start + count;
00655 }
00656 
00657 void
00658 _IO_init_wmarker (marker, fp)
00659      struct _IO_marker *marker;
00660      _IO_FILE *fp;
00661 {
00662   marker->_sbuf = fp;
00663   if (_IO_in_put_mode (fp))
00664     INTUSE(_IO_switch_to_wget_mode) (fp);
00665   if (_IO_in_backup (fp))
00666     marker->_pos = fp->_wide_data->_IO_read_ptr - fp->_wide_data->_IO_read_end;
00667   else
00668     marker->_pos = (fp->_wide_data->_IO_read_ptr
00669                   - fp->_wide_data->_IO_read_base);
00670 
00671   /* Should perhaps sort the chain? */
00672   marker->_next = fp->_markers;
00673   fp->_markers = marker;
00674 }
00675 
00676 #define BAD_DELTA EOF
00677 
00678 /* Return difference between MARK and current position of MARK's stream. */
00679 int
00680 _IO_wmarker_delta (mark)
00681      struct _IO_marker *mark;
00682 {
00683   int cur_pos;
00684   if (mark->_sbuf == NULL)
00685     return BAD_DELTA;
00686   if (_IO_in_backup (mark->_sbuf))
00687     cur_pos = (mark->_sbuf->_wide_data->_IO_read_ptr
00688               - mark->_sbuf->_wide_data->_IO_read_end);
00689   else
00690     cur_pos = (mark->_sbuf->_wide_data->_IO_read_ptr
00691               - mark->_sbuf->_wide_data->_IO_read_base);
00692   return mark->_pos - cur_pos;
00693 }
00694 
00695 int
00696 _IO_seekwmark (fp, mark, delta)
00697      _IO_FILE *fp;
00698      struct _IO_marker *mark;
00699      int delta;
00700 {
00701   if (mark->_sbuf != fp)
00702     return EOF;
00703  if (mark->_pos >= 0)
00704     {
00705       if (_IO_in_backup (fp))
00706        INTUSE(_IO_switch_to_main_wget_area) (fp);
00707       fp->_wide_data->_IO_read_ptr = (fp->_wide_data->_IO_read_base
00708                                   + mark->_pos);
00709     }
00710   else
00711     {
00712       if (!_IO_in_backup (fp))
00713        INTUSE(_IO_switch_to_wbackup_area) (fp);
00714       fp->_wide_data->_IO_read_ptr = fp->_wide_data->_IO_read_end + mark->_pos;
00715     }
00716   return 0;
00717 }
00718 
00719 void
00720 _IO_unsave_wmarkers (fp)
00721      _IO_FILE *fp;
00722 {
00723   struct _IO_marker *mark = fp->_markers;
00724   if (mark)
00725     {
00726 #ifdef TODO
00727       streampos offset = seekoff (0, ios::cur, ios::in);
00728       if (offset != EOF)
00729        {
00730          offset += eGptr () - Gbase ();
00731          for ( ; mark != NULL; mark = mark->_next)
00732            mark->set_streampos (mark->_pos + offset);
00733        }
00734     else
00735       {
00736        for ( ; mark != NULL; mark = mark->_next)
00737          mark->set_streampos (EOF);
00738       }
00739 #endif
00740       fp->_markers = 0;
00741     }
00742 
00743   if (_IO_have_backup (fp))
00744     INTUSE(_IO_free_wbackup_area) (fp);
00745 }