diff options
Diffstat (limited to 'libio')
80 files changed, 4568 insertions, 199 deletions
diff --git a/libio/Makefile b/libio/Makefile index 948556e15c..6fcde40814 100644 --- a/libio/Makefile +++ b/libio/Makefile @@ -25,11 +25,16 @@ headers := stdio.h libio.h _G_config.h bits/stdio.h routines := \ filedoalloc iofclose iofdopen iofflush iofgetpos iofgets iofopen \ - iofopncook iofputs iofread iofsetpos ioftell \ + iofopncook iofputs iofread iofsetpos ioftell wfiledoalloc \ iofwrite iogetdelim iogetline iogets iopadn iopopen ioputs \ ioseekoff ioseekpos iosetbuffer iosetvbuf iosprintf ioungetc \ iovsprintf iovsscanf \ iofgetpos64 iofopen64 iofsetpos64 \ + oldiofgetpos oldiofgetpos64 oldiofsetpos oldiofsetpos64 \ + fputwc fputwc_u getwc getwc_u getwchar getwchar_u iofgetws iofgetws_u \ + iofputws iofputws_u iogetwline iowpadn ioungetwc putwc putwc_u \ + putchar putchar_u swprintf vwprintf wprintf wscanf fwscanf vwscanf \ + vswprintf iovswscanf swscanf wgenops wstrops wfileops iofwide \ \ clearerr feof ferror fileno fputc freopen fseek getc getchar \ memstream pclose putc putchar rewind setbuf setlinebuf vasprintf \ @@ -38,6 +43,8 @@ routines := \ \ libc_fatal +tests = tst_swprintf tst_wprintf tst_swscanf tst_wscanf + all: # Make this the default target; it will be defined in Rules. include ../Makeconfig diff --git a/libio/Versions b/libio/Versions index 61b767a2d3..c7a5f668a1 100644 --- a/libio/Versions +++ b/libio/Versions @@ -100,4 +100,31 @@ libc { # p* pclose; popen; } + GLIBC_2.2 { + # functions used in libstdc++ + _IO_fgetpos; _IO_fgetpos64; _IO_fsetpos; _IO_fsetpos64; + + # f* + fgetpos; fgetpos64; fgetwc; fgetwc_unlocked; fgetws; fgetws_unlocked; + fputwc; fputwc_unlocked; fputws; fputws_unlocked; fsetpos; fsetpos64; + fwide; fwprintf; fwscanf; + + # g* + getwc; getwc_unlocked; getwchar; getwchar_unlocked; + + # p* + putwc; putwc_unlocked; putwchar; putwchar_unlocked; + + # s* + swprintf; swscanf; + + # u* + ungetwc; + + # v* + vfwprintf; vswprintf; vwprintf; vfwscanf; vswscanf; vwscanf; + + # w* + wprintf; wscanf; + } } diff --git a/libio/fileops.c b/libio/fileops.c index f5ec0e2b9e..8d480ad08b 100644 --- a/libio/fileops.c +++ b/libio/fileops.c @@ -1,4 +1,4 @@ -/* Copyright (C) 1993, 1995, 1997, 1998 Free Software Foundation, Inc. +/* Copyright (C) 1993, 1995, 1997, 1998, 1999 Free Software Foundation, Inc. This file is part of the GNU IO Library. Written by Per Bothner <bothner@cygnus.com>. @@ -136,9 +136,18 @@ _IO_new_file_close_it (fp) close_status = _IO_SYSCLOSE (fp); /* Free buffer. */ - _IO_setb (fp, NULL, NULL, 0); - _IO_setg (fp, NULL, NULL, NULL); - _IO_setp (fp, NULL, NULL); + if (fp->_mode <= 0) + { + _IO_setb (fp, NULL, NULL, 0); + _IO_setg (fp, NULL, NULL, NULL); + _IO_setp (fp, NULL, NULL); + } + else + { + _IO_wsetb (fp, NULL, NULL, 0); + _IO_wsetg (fp, NULL, NULL, NULL); + _IO_wsetp (fp, NULL, NULL); + } _IO_un_link (fp); fp->_flags = _IO_MAGIC|CLOSED_FILEBUF_FLAGS; @@ -277,14 +286,14 @@ _IO_new_file_setbuf (fp, p, len) char *p; _IO_ssize_t len; { - if (_IO_default_setbuf (fp, p, len) == NULL) - return NULL; + if (_IO_default_setbuf (fp, p, len) == NULL) + return NULL; - fp->_IO_write_base = fp->_IO_write_ptr = fp->_IO_write_end - = fp->_IO_buf_base; - _IO_setg (fp, fp->_IO_buf_base, fp->_IO_buf_base, fp->_IO_buf_base); + fp->_IO_write_base = fp->_IO_write_ptr = fp->_IO_write_end + = fp->_IO_buf_base; + _IO_setg (fp, fp->_IO_buf_base, fp->_IO_buf_base, fp->_IO_buf_base); - return fp; + return fp; } static int new_do_write __P ((_IO_FILE *, const char *, _IO_size_t)); @@ -319,7 +328,7 @@ new_do_write (fp, data, to_do) fp->_offset = _IO_pos_BAD; else if (fp->_IO_read_end != fp->_IO_write_base) { - _IO_fpos64_t new_pos + _IO_off64_t new_pos = _IO_SYSSEEK (fp, fp->_IO_write_base - fp->_IO_read_end, 1); if (new_pos == _IO_pos_BAD) return 0; @@ -330,7 +339,8 @@ new_do_write (fp, data, to_do) fp->_cur_column = _IO_adjust_column (fp->_cur_column - 1, data, count) + 1; _IO_setg (fp, fp->_IO_buf_base, fp->_IO_buf_base, fp->_IO_buf_base); fp->_IO_write_base = fp->_IO_write_ptr = fp->_IO_buf_base; - fp->_IO_write_end = ((fp->_flags & (_IO_LINE_BUF+_IO_UNBUFFERED)) + fp->_IO_write_end = (fp->_mode < 0 + && (fp->_flags & (_IO_LINE_BUF+_IO_UNBUFFERED)) ? fp->_IO_buf_base : fp->_IO_buf_end); return count; } @@ -410,7 +420,7 @@ _IO_new_file_overflow (f, ch) return EOF; } /* If currently reading or no buffer allocated. */ - if ((f->_flags & _IO_CURRENTLY_PUTTING) == 0) + if ((f->_flags & _IO_CURRENTLY_PUTTING) == 0 || f->_IO_write_base == 0) { /* Allocate a buffer if needed. */ if (f->_IO_write_base == 0) @@ -433,18 +443,20 @@ _IO_new_file_overflow (f, ch) f->_IO_read_base = f->_IO_read_ptr = f->_IO_read_end; f->_flags |= _IO_CURRENTLY_PUTTING; - if (f->_flags & (_IO_LINE_BUF+_IO_UNBUFFERED)) + if (f->_mode < 0 && f->_flags & (_IO_LINE_BUF+_IO_UNBUFFERED)) f->_IO_write_end = f->_IO_write_ptr; } if (ch == EOF) - return _IO_do_flush (f); + return _IO_new_do_write(f, f->_IO_write_base, + f->_IO_write_ptr - f->_IO_write_base); if (f->_IO_write_ptr == f->_IO_buf_end ) /* Buffer is really full */ if (_IO_do_flush (f) == EOF) return EOF; *f->_IO_write_ptr++ = ch; if ((f->_flags & _IO_UNBUFFERED) || ((f->_flags & _IO_LINE_BUF) && ch == '\n')) - if (_IO_do_flush (f) == EOF) + if (_IO_new_do_write(f, f->_IO_write_base, + f->_IO_write_ptr - f->_IO_write_base) == EOF) return EOF; return (unsigned char) ch; } @@ -483,14 +495,14 @@ _IO_new_file_sync (fp) return retval; } -_IO_fpos64_t +_IO_off64_t _IO_new_file_seekoff (fp, offset, dir, mode) _IO_FILE *fp; _IO_off64_t offset; int dir; int mode; { - _IO_fpos64_t result; + _IO_off64_t result; _IO_off64_t delta, new_offset; long count; /* POSIX.1 8.2.3.7 says that after a call the fflush() the file @@ -534,7 +546,7 @@ _IO_new_file_seekoff (fp, offset, dir, mode) if (fp->_offset == _IO_pos_BAD) goto dumb; /* Make offset absolute, assuming current pointer is file_ptr(). */ - offset += _IO_pos_as_off (fp->_offset); + offset += fp->_offset; dir = _IO_seek_set; break; @@ -563,8 +575,8 @@ _IO_new_file_seekoff (fp, offset, dir, mode) && !_IO_in_backup (fp)) { /* Offset relative to start of main get area. */ - _IO_fpos64_t rel_offset = (offset - fp->_offset - + (fp->_IO_read_end - fp->_IO_read_base)); + _IO_off64_t rel_offset = (offset - fp->_offset + + (fp->_IO_read_end - fp->_IO_read_base)); if (rel_offset >= 0) { #if 0 @@ -678,7 +690,7 @@ _IO_file_read (fp, buf, size) return read (fp->_fileno, buf, size); } -_IO_fpos64_t +_IO_off64_t _IO_file_seek (fp, offset, dir) _IO_FILE *fp; _IO_off64_t offset; @@ -720,7 +732,7 @@ _IO_new_file_write (f, data, n) while (to_do > 0) { _IO_ssize_t count = write (f->_fileno, data, to_do); - if (count == EOF) + if (count < 0) { f->_flags |= _IO_ERR_SEEN; break; @@ -740,7 +752,7 @@ _IO_new_file_xsputn (f, data, n) const void *data; _IO_size_t n; { - register const char *s = (char *) data; + register const char *s = (const char *) data; _IO_size_t to_do = n; int must_flush = 0; _IO_size_t count; diff --git a/libio/fputwc.c b/libio/fputwc.c new file mode 100644 index 0000000000..cc8451a98f --- /dev/null +++ b/libio/fputwc.c @@ -0,0 +1,45 @@ +/* Copyright (C) 1993, 1996, 1997, 1998, 1999 Free Software Foundation, Inc. + This file is part of the GNU IO Library. + + This library is free software; you can redistribute it and/or + modify it under the terms of the GNU General Public License as + published by the Free Software Foundation; either version 2, or (at + your option) any later version. + + This library is distributed in the hope that it will be useful, but + WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this library; see the file COPYING. If not, write to + the Free Software Foundation, 59 Temple Place - Suite 330, Boston, + MA 02111-1307, USA. + + As a special exception, if you link this library with files + compiled with a GNU compiler to produce an executable, this does + not cause the resulting executable to be covered by the GNU General + Public License. This exception does not however invalidate any + other reasons why the executable file might be covered by the GNU + General Public License. */ + +#include "libioP.h" +#include <wchar.h> + +wint_t +fputwc (wc, fp) + wint_t wc; + _IO_FILE *fp; +{ + int result; + CHECK_FILE (fp, EOF); + _IO_cleanup_region_start ((void (*) __P ((void *))) _IO_funlockfile, fp); + _IO_flockfile (fp); + if (_IO_fwide (fp, 1) < 0) + result = WEOF; + else + result = _IO_putwc_unlocked (wc, fp); + _IO_funlockfile (fp); + _IO_cleanup_region_end (0); + return result; +} diff --git a/libio/fputwc_u.c b/libio/fputwc_u.c new file mode 100644 index 0000000000..343e34d90e --- /dev/null +++ b/libio/fputwc_u.c @@ -0,0 +1,40 @@ +/* Copyright (C) 1993, 1996, 1997, 1999 Free Software Foundation, Inc. + This file is part of the GNU IO Library. + + This library is free software; you can redistribute it and/or + modify it under the terms of the GNU General Public License as + published by the Free Software Foundation; either version 2, or (at + your option) any later version. + + This library is distributed in the hope that it will be useful, but + WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this library; see the file COPYING. If not, write to + the Free Software Foundation, 59 Temple Place - Suite 330, Boston, + MA 02111-1307, USA. + + As a special exception, if you link this library with files + compiled with a GNU compiler to produce an executable, this does + not cause the resulting executable to be covered by the GNU General + Public License. This exception does not however invalidate any + other reasons why the executable file might be covered by the GNU + General Public License. */ + +#include "libioP.h" +#include <wchar.h> + +#undef fputwc_unlocked + +wint_t +fputwc_unlocked (wc, fp) + wint_t wc; + _IO_FILE *fp; +{ + CHECK_FILE (fp, EOF); + if (_IO_fwide (fp, 1) < 0) + return WEOF; + return _IO_putwc_unlocked (wc, fp); +} diff --git a/libio/ftello.c b/libio/ftello.c index 2d8a8a7167..ed4ef8b603 100644 --- a/libio/ftello.c +++ b/libio/ftello.c @@ -1,4 +1,4 @@ -/* Copyright (C) 1993, 1995, 1996, 1997, 1998 Free Software Foundation, Inc. +/* Copyright (C) 1993, 95, 96, 97, 98, 99 Free Software Foundation, Inc. This file is part of the GNU IO Library. This library is free software; you can redistribute it and/or @@ -32,13 +32,19 @@ off_t ftello (fp) _IO_FILE *fp; { - _IO_pos_t pos; + _IO_off_t pos; CHECK_FILE (fp, -1L); _IO_cleanup_region_start ((void (*) __P ((void *))) _IO_funlockfile, fp); _IO_flockfile (fp); pos = _IO_seekoff (fp, 0, _IO_seek_cur, 0); if (_IO_in_backup (fp)) - pos -= fp->_IO_save_end - fp->_IO_save_base; + { + if (fp->_mode <= 0) + pos -= fp->_IO_save_end - fp->_IO_save_base; + else + /* XXX Not done yet. */ + abort (); + } _IO_funlockfile (fp); _IO_cleanup_region_end (0); if (pos == _IO_pos_BAD) @@ -49,5 +55,5 @@ ftello (fp) #endif return -1L; } - return _IO_pos_as_off (pos); + return pos; } diff --git a/libio/ftello64.c b/libio/ftello64.c index 621454974e..7cb75626cf 100644 --- a/libio/ftello64.c +++ b/libio/ftello64.c @@ -1,4 +1,4 @@ -/* Copyright (C) 1993, 1995, 1996, 1997, 1998 Free Software Foundation, Inc. +/* Copyright (C) 1993, 95, 96, 97, 98, 99 Free Software Foundation, Inc. This file is part of the GNU IO Library. This library is free software; you can redistribute it and/or @@ -33,13 +33,18 @@ ftello64 (fp) _IO_FILE *fp; { #ifdef _G_LSEEK64 - _IO_pos_t pos; + _IO_off64_t pos; CHECK_FILE (fp, -1L); _IO_cleanup_region_start ((void (*) __P ((void *))) _IO_funlockfile, fp); _IO_flockfile (fp); pos = _IO_seekoff (fp, 0, _IO_seek_cur, 0); if (_IO_in_backup (fp)) - pos -= fp->_IO_save_end - fp->_IO_save_base; + { + if (fp->_mode <= 0) + pos -= fp->_IO_save_end - fp->_IO_save_base; + else + abort (); + } _IO_funlockfile (fp); _IO_cleanup_region_end (0); if (pos == _IO_pos_BAD) @@ -50,7 +55,7 @@ ftello64 (fp) #endif return -1L; } - return _IO_pos_as_off (pos); + return pos; #else __set_errno (ENOSYS); return -1; diff --git a/libio/fwprintf.c b/libio/fwprintf.c new file mode 100644 index 0000000000..c26a2ffcd3 --- /dev/null +++ b/libio/fwprintf.c @@ -0,0 +1,36 @@ +/* Copyright (C) 1991, 1997, 1999 Free Software Foundation, Inc. + This file is part of the GNU C Library. + + The GNU C Library is free software; you can redistribute it and/or + modify it under the terms of the GNU Library General Public License as + published by the Free Software Foundation; either version 2 of the + License, or (at your option) any later version. + + The GNU C Library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Library General Public License for more details. + + You should have received a copy of the GNU Library General Public + License along with the GNU C Library; see the file COPYING.LIB. If not, + write to the Free Software Foundation, Inc., 59 Temple Place - Suite 330, + Boston, MA 02111-1307, USA. */ + +#include <stdarg.h> +#include <wchar.h> + + +/* Write formatted output to STREAM from the format string FORMAT. */ +/* VARARGS2 */ +int +fwprintf (FILE *stream, const wchar_t *format, ...) +{ + va_list arg; + int done; + + va_start (arg, format); + done = vfwprintf (stream, format, arg); + va_end (arg); + + return done; +} diff --git a/libio/fwscanf.c b/libio/fwscanf.c new file mode 100644 index 0000000000..4510fc5b5f --- /dev/null +++ b/libio/fwscanf.c @@ -0,0 +1,35 @@ +/* Copyright (C) 1991, 1997, 1999 Free Software Foundation, Inc. + This file is part of the GNU C Library. + + The GNU C Library is free software; you can redistribute it and/or + modify it under the terms of the GNU Library General Public License as + published by the Free Software Foundation; either version 2 of the + License, or (at your option) any later version. + + The GNU C Library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Library General Public License for more details. + + You should have received a copy of the GNU Library General Public + License along with the GNU C Library; see the file COPYING.LIB. If not, + write to the Free Software Foundation, Inc., 59 Temple Place - Suite 330, + Boston, MA 02111-1307, USA. */ + +#include <stdarg.h> +#include <wchar.h> + +/* Read formatted input from STREAM according to the format string FORMAT. */ +/* VARARGS2 */ +int +fwscanf (FILE *stream, const wchar_t *format, ...) +{ + va_list arg; + int done; + + va_start (arg, format); + done = __vfwscanf (stream, format, arg); + va_end (arg); + + return done; +} diff --git a/libio/genops.c b/libio/genops.c index 81752e3ccc..a8f34463ad 100644 --- a/libio/genops.c +++ b/libio/genops.c @@ -80,9 +80,9 @@ _IO_link_in (fp) /* Return minimum _pos markers Assumes the current get area is the main get area. */ -static _IO_ssize_t _IO_least_marker __P ((_IO_FILE *fp, char *end_p)); +_IO_ssize_t _IO_least_marker __P ((_IO_FILE *fp, char *end_p)); -static _IO_ssize_t +_IO_ssize_t _IO_least_marker (fp, end_p) _IO_FILE *fp; char *end_p; @@ -282,6 +282,9 @@ int __underflow (fp) _IO_FILE *fp; { + if (_IO_fwide (fp, -1) != -1) + return EOF; + if (_IO_in_put_mode (fp)) if (_IO_switch_to_get_mode (fp) == EOF) return EOF; @@ -307,6 +310,9 @@ int __uflow (fp) _IO_FILE *fp; { + if (_IO_fwide (fp, -1) != -1) + return EOF; + if (_IO_in_put_mode (fp)) if (_IO_switch_to_get_mode (fp) == EOF) return EOF; @@ -508,13 +514,13 @@ _IO_default_setbuf (fp, p, len) return fp; } -_IO_fpos64_t +_IO_off64_t _IO_default_seekpos (fp, pos, mode) _IO_FILE *fp; - _IO_fpos64_t pos; + _IO_off64_t pos; int mode; { - return _IO_SEEKOFF (fp, _IO_pos_as_off (pos), 0, mode); + return _IO_SEEKOFF (fp, pos, 0, mode); } int @@ -533,6 +539,17 @@ _IO_init (fp, flags) _IO_FILE *fp; int flags; { + _IO_no_init (fp, flags, -1, NULL, NULL); +} + +void +_IO_no_init (fp, flags, orientation, wd, jmp) + _IO_FILE *fp; + int flags; + int orientation; + struct _IO_wide_data *wd; + struct _IO_jump_t *jmp; +{ fp->_flags = _IO_MAGIC|flags; fp->_IO_buf_base = NULL; fp->_IO_buf_end = NULL; @@ -555,6 +572,24 @@ _IO_init (fp, flags) #ifdef _IO_MTSAFE_IO _IO_lock_init (*fp->_lock); #endif + fp->_mode = orientation; + if (orientation >= 0) + { + fp->_wide_data = wd; + fp->_wide_data->_IO_buf_base = NULL; + fp->_wide_data->_IO_buf_end = NULL; + fp->_wide_data->_IO_read_base = NULL; + fp->_wide_data->_IO_read_ptr = NULL; + fp->_wide_data->_IO_read_end = NULL; + fp->_wide_data->_IO_write_base = NULL; + fp->_wide_data->_IO_write_ptr = NULL; + fp->_wide_data->_IO_write_end = NULL; + fp->_wide_data->_IO_save_base = NULL; + fp->_wide_data->_IO_backup_base = NULL; + fp->_wide_data->_IO_save_end = NULL; + + fp->_wide_data->_wide_vtable = jmp; + } } int @@ -595,7 +630,7 @@ _IO_default_finish (fp, dummy) _IO_un_link (fp); } -_IO_fpos64_t +_IO_off64_t _IO_default_seekoff (fp, offset, dir, mode) _IO_FILE *fp; _IO_off64_t offset; @@ -706,7 +741,9 @@ _IO_flush_all () int result = 0; _IO_FILE *fp; for (fp = _IO_list_all; fp != NULL; fp = fp->_chain) - if (fp->_IO_write_ptr > fp->_IO_write_base + if (((fp->_mode < 0 && fp->_IO_write_ptr > fp->_IO_write_base) + || (fp->_mode > 0 && (fp->_wide_data->_IO_write_ptr + > fp->_wide_data->_IO_write_base))) && _IO_OVERFLOW (fp, EOF) == EOF) result = EOF; return result; @@ -941,7 +978,7 @@ _IO_default_pbackfail (fp, c) return (unsigned char) c; } -_IO_fpos64_t +_IO_off64_t _IO_default_seek (fp, offset, dir) _IO_FILE *fp; _IO_off64_t offset; diff --git a/libio/getwc.c b/libio/getwc.c new file mode 100644 index 0000000000..0829ea0248 --- /dev/null +++ b/libio/getwc.c @@ -0,0 +1,50 @@ +/* Copyright (C) 1993, 95, 96, 97, 98, 99 Free Software Foundation, Inc. + This file is part of the GNU IO Library. + + This library is free software; you can redistribute it and/or + modify it under the terms of the GNU General Public License as + published by the Free Software Foundation; either version 2, or (at + your option) any later version. + + This library is distributed in the hope that it will be useful, but + WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this library; see the file COPYING. If not, write to + the Free Software Foundation, 59 Temple Place - Suite 330, Boston, + MA 02111-1307, USA. + + As a special exception, if you link this library with files + compiled with a GNU compiler to produce an executable, this does + not cause the resulting executable to be covered by the GNU General + Public License. This exception does not however invalidate any + other reasons why the executable file might be covered by the GNU + General Public License. */ + +#include "libioP.h" +#include <wchar.h> + +#undef _IO_getwc + +wint_t +_IO_getwc (fp) + FILE *fp; +{ + wint_t result; + CHECK_FILE (fp, WEOF); + _IO_cleanup_region_start ((void (*) __P ((void *))) _IO_funlockfile, fp); + _IO_flockfile (fp); + result = _IO_getwc_unlocked (fp); + _IO_funlockfile (fp); + _IO_cleanup_region_end (0); + return result; +} + +#undef getwc + +#ifdef weak_alias +weak_alias (_IO_getwc, getwc) +weak_alias (_IO_getwc, fgetwc) +#endif diff --git a/libio/getwc_u.c b/libio/getwc_u.c new file mode 100644 index 0000000000..606b4d24cc --- /dev/null +++ b/libio/getwc_u.c @@ -0,0 +1,39 @@ +/* Copyright (C) 1993, 1995, 1996, 1997, 1999 Free Software Foundation, Inc. + This file is part of the GNU IO Library. + + This library is free software; you can redistribute it and/or + modify it under the terms of the GNU General Public License as + published by the Free Software Foundation; either version 2, or (at + your option) any later version. + + This library is distributed in the hope that it will be useful, but + WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this library; see the file COPYING. If not, write to + the Free Software Foundation, 59 Temple Place - Suite 330, Boston, + MA 02111-1307, USA. + + As a special exception, if you link this library with files + compiled with a GNU compiler to produce an executable, this does + not cause the resulting executable to be covered by the GNU General + Public License. This exception does not however invalidate any + other reasons why the executable file might be covered by the GNU + General Public License. */ + +#include "libioP.h" +#include "stdio.h" + +#undef getwc_unlocked + +wint_t +__getwc_unlocked (FILE *fp) +{ + CHECK_FILE (fp, EOF); + return _IO_getwc_unlocked (fp); +} + +weak_alias (__getwc_unlocked, getwc_unlocked) +weak_alias (__getwc_unlocked, fgetwc_unlocked) diff --git a/libio/getwchar.c b/libio/getwchar.c new file mode 100644 index 0000000000..6ef1f9b552 --- /dev/null +++ b/libio/getwchar.c @@ -0,0 +1,42 @@ +/* Copyright (C) 1993, 1996, 1997, 1998, 1999 Free Software Foundation, Inc. + This file is part of the GNU IO Library. + + This library is free software; you can redistribute it and/or + modify it under the terms of the GNU General Public License as + published by the Free Software Foundation; either version 2, or (at + your option) any later version. + + This library is distributed in the hope that it will be useful, but + WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this library; see the file COPYING. If not, write to + the Free Software Foundation, 59 Temple Place - Suite 330, Boston, + MA 02111-1307, USA. + + As a special exception, if you link this library with files + compiled with a GNU compiler to produce an executable, this does + not cause the resulting executable to be covered by the GNU General + Public License. This exception does not however invalidate any + other reasons why the executable file might be covered by the GNU + General Public License. */ + +#include "libioP.h" +#include <wchar.h> + +#undef getwchar + +wint_t +getwchar () +{ + wint_t result; + _IO_cleanup_region_start ((void (*) __P ((void *))) _IO_funlockfile, + _IO_stdin); + _IO_flockfile (_IO_stdin); + result = _IO_getwc_unlocked (_IO_stdin); + _IO_funlockfile (_IO_stdin); + _IO_cleanup_region_end (0); + return result; +} diff --git a/libio/getwchar_u.c b/libio/getwchar_u.c new file mode 100644 index 0000000000..18dc2ca158 --- /dev/null +++ b/libio/getwchar_u.c @@ -0,0 +1,35 @@ +/* Copyright (C) 1993, 1996, 1997, 1999 Free Software Foundation, Inc. + This file is part of the GNU IO Library. + + This library is free software; you can redistribute it and/or + modify it under the terms of the GNU General Public License as + published by the Free Software Foundation; either version 2, or (at + your option) any later version. + + This library is distributed in the hope that it will be useful, but + WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this library; see the file COPYING. If not, write to + the Free Software Foundation, 59 Temple Place - Suite 330, Boston, + MA 02111-1307, USA. + + As a special exception, if you link this library with files + compiled with a GNU compiler to produce an executable, this does + not cause the resulting executable to be covered by the GNU General + Public License. This exception does not however invalidate any + other reasons why the executable file might be covered by the GNU + General Public License. */ + +#include "libioP.h" +#include <wchar.h> + +#undef getwchar_unlocked + +wint_t +getwchar_unlocked () +{ + return _IO_getwc_unlocked (_IO_stdin); +} diff --git a/libio/iofdopen.c b/libio/iofdopen.c index 40419bd267..3bfa40c7c6 100644 --- a/libio/iofdopen.c +++ b/libio/iofdopen.c @@ -1,4 +1,4 @@ -/* Copyright (C) 1993, 1994, 1997, 1998 Free Software Foundation, Inc. +/* Copyright (C) 1993, 1994, 1997, 1998, 1999 Free Software Foundation, Inc. This file is part of the GNU IO Library. This library is free software; you can redistribute it and/or @@ -50,6 +50,7 @@ _IO_new_fdopen (fd, mode) #ifdef _IO_MTSAFE_IO _IO_lock_t lock; #endif + struct _IO_wide_data wd; } *new_f; int fd_flags; @@ -112,7 +113,7 @@ _IO_new_fdopen (fd, mode) #ifdef _IO_MTSAFE_IO new_f->fp.file._lock = &new_f->lock; #endif - _IO_init (&new_f->fp.file, 0); + _IO_no_init (&new_f->fp.file, 0, 0, &new_f->wd, &_IO_wfile_jumps); _IO_JUMPS (&new_f->fp) = &_IO_file_jumps; _IO_file_init (&new_f->fp.file); #if !_IO_UNIFIED_JUMPTABLES diff --git a/libio/iofgetpos.c b/libio/iofgetpos.c index 27f018d07f..5b8f6a4129 100644 --- a/libio/iofgetpos.c +++ b/libio/iofgetpos.c @@ -1,4 +1,4 @@ -/* Copyright (C) 1993, 1995, 1996, 1997, 1998 Free Software Foundation, Inc. +/* Copyright (C) 1993, 95, 96, 97, 98, 99 Free Software Foundation, Inc. This file is part of the GNU IO Library. This library is free software; you can redistribute it and/or @@ -27,11 +27,11 @@ #include <errno.h> int -_IO_fgetpos (fp, posp) +_IO_new_fgetpos (fp, posp) _IO_FILE *fp; _IO_fpos_t *posp; { - _IO_fpos_t pos; + _IO_off_t pos; CHECK_FILE (fp, EOF); _IO_cleanup_region_start ((void (*) __P ((void *))) _IO_funlockfile, fp); _IO_flockfile (fp); @@ -50,10 +50,16 @@ _IO_fgetpos (fp, posp) #endif return EOF; } - *posp = pos; + posp->__pos = pos; + if (fp->_mode > 0 + && (*fp->_codecvt->__codecvt_do_encoding) (fp->_codecvt) < 0) + /* This is a stateful encoding, safe the state. */ + posp->__state = fp->_wide_data->_IO_state; return 0; } #ifdef weak_alias -weak_alias (_IO_fgetpos, fgetpos) +strong_alias (_IO_new_fgetpos, __new_fgetpos) +default_symbol_version (_IO_new_fgetpos, _IO_fgetpos, GLIBC_2.2); +default_symbol_version (__new_fgetpos, fgetpos, GLIBC_2.2); #endif diff --git a/libio/iofgetpos64.c b/libio/iofgetpos64.c index a705e9e91a..cc39a3a9e1 100644 --- a/libio/iofgetpos64.c +++ b/libio/iofgetpos64.c @@ -1,4 +1,4 @@ -/* Copyright (C) 1993, 1995, 1996, 1997, 1998 Free Software Foundation, Inc. +/* Copyright (C) 1993, 95, 96, 97, 98, 99 Free Software Foundation, Inc. This file is part of the GNU IO Library. This library is free software; you can redistribute it and/or @@ -27,12 +27,12 @@ #include <errno.h> int -_IO_fgetpos64 (fp, posp) +_IO_new_fgetpos64 (fp, posp) _IO_FILE *fp; _IO_fpos64_t *posp; { #ifdef _G_LSEEK64 - _IO_fpos64_t pos; + _IO_off64_t pos; CHECK_FILE (fp, EOF); _IO_cleanup_region_start ((void (*) __P ((void *))) _IO_funlockfile, fp); _IO_flockfile (fp); @@ -45,13 +45,17 @@ _IO_fgetpos64 (fp, posp) { /* ANSI explicitly requires setting errno to a positive value on failure. */ -#ifdef EIO +# ifdef EIO if (errno == 0) __set_errno (EIO); -#endif +# endif return EOF; } - *posp = pos; + posp->__pos = pos; + if (fp->_mode > 0 + && (*fp->_codecvt->__codecvt_do_encoding) (fp->_codecvt) < 0) + /* This is a stateful encoding, safe the state. */ + posp->__state = fp->_wide_data->_IO_state; return 0; #else __set_errno (ENOSYS); @@ -60,5 +64,7 @@ _IO_fgetpos64 (fp, posp) } #ifdef weak_alias -weak_alias (_IO_fgetpos64, fgetpos64) +default_symbol_version (_IO_new_fgetpos64, _IO_fgetpos64, GLIBC_2.2); +strong_alias (_IO_new_fgetpos64, __new_fgetpos64) +default_symbol_version (__new_fgetpos64, fgetpos64, GLIBC_2.2); #endif diff --git a/libio/iofgetws.c b/libio/iofgetws.c new file mode 100644 index 0000000000..25ed836560 --- /dev/null +++ b/libio/iofgetws.c @@ -0,0 +1,63 @@ +/* Copyright (C) 1993, 95, 96, 97, 98, 99 Free Software Foundation, Inc. + This file is part of the GNU IO Library. + + This library is free software; you can redistribute it and/or + modify it under the terms of the GNU General Public License as + published by the Free Software Foundation; either version 2, or (at + your option) any later version. + + This library is distributed in the hope that it will be useful, but + WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this library; see the file COPYING. If not, write to + the Free Software Foundation, 59 Temple Place - Suite 330, Boston, + MA 02111-1307, USA. + + As a special exception, if you link this library with files + compiled with a GNU compiler to produce an executable, this does + not cause the resulting executable to be covered by the GNU General + Public License. This exception does not however invalidate any + other reasons why the executable file might be covered by the GNU + General Public License. */ + +#include "libioP.h" +#include <wchar.h> + +wchar_t * +fgetws (buf, n, fp) + wchar_t *buf; + int n; + _IO_FILE *fp; +{ + _IO_size_t count; + wchar_t *result; + int old_error; + CHECK_FILE (fp, NULL); + if (n <= 0) + return NULL; + _IO_cleanup_region_start ((void (*) __P ((void *))) _IO_funlockfile, fp); + _IO_flockfile (fp); + /* This is very tricky since a file descriptor may be in the + non-blocking mode. The error flag doesn't mean much in this + case. We return an error only when there is a new error. */ + old_error = fp->_IO_file_flags & _IO_ERR_SEEN; + fp->_IO_file_flags &= ~_IO_ERR_SEEN; + count = _IO_getwline (fp, buf, n - 1, L'\n', 1); + /* If we read in some bytes and errno is EAGAIN, that error will + be reported for next read. */ + if (count == 0 || ((fp->_IO_file_flags & _IO_ERR_SEEN) + && errno != EAGAIN)) + result = NULL; + else + { + buf[count] = '\0'; + result = buf; + } + fp->_IO_file_flags |= old_error; + _IO_funlockfile (fp); + _IO_cleanup_region_end (0); + return result; +} diff --git a/libio/iofgetws_u.c b/libio/iofgetws_u.c new file mode 100644 index 0000000000..951ab80d9d --- /dev/null +++ b/libio/iofgetws_u.c @@ -0,0 +1,59 @@ +/* Copyright (C) 1993, 95, 96, 97, 98, 99 Free Software Foundation, Inc. + This file is part of the GNU IO Library. + + This library is free software; you can redistribute it and/or + modify it under the terms of the GNU General Public License as + published by the Free Software Foundation; either version 2, or (at + your option) any later version. + + This library is distributed in the hope that it will be useful, but + WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this library; see the file COPYING. If not, write to + the Free Software Foundation, 59 Temple Place - Suite 330, Boston, + MA 02111-1307, USA. + + As a special exception, if you link this library with files + compiled with a GNU compiler to produce an executable, this does + not cause the resulting executable to be covered by the GNU General + Public License. This exception does not however invalidate any + other reasons why the executable file might be covered by the GNU + General Public License. */ + +#include "libioP.h" +#include <wchar.h> + +wchar_t * +fgetws_unlocked (buf, n, fp) + wchar_t *buf; + int n; + _IO_FILE *fp; +{ + _IO_size_t count; + wchar_t *result; + int old_error; + CHECK_FILE (fp, NULL); + if (n <= 0) + return NULL; + /* This is very tricky since a file descriptor may be in the + non-blocking mode. The error flag doesn't mean much in this + case. We return an error only when there is a new error. */ + old_error = fp->_IO_file_flags & _IO_ERR_SEEN; + fp->_IO_file_flags &= ~_IO_ERR_SEEN; + count = _IO_getwline (fp, buf, n - 1, L'\n', 1); + /* If we read in some bytes and errno is EAGAIN, that error will + be reported for next read. */ + if (count == 0 || ((fp->_IO_file_flags & _IO_ERR_SEEN) + && errno != EAGAIN)) + result = NULL; + else + { + buf[count] = '\0'; + result = buf; + } + fp->_IO_file_flags |= old_error; + return result; +} diff --git a/libio/iofopen.c b/libio/iofopen.c index 92d58bb133..60b15a00f8 100644 --- a/libio/iofopen.c +++ b/libio/iofopen.c @@ -39,6 +39,7 @@ _IO_new_fopen (filename, mode) #ifdef _IO_MTSAFE_IO _IO_lock_t lock; #endif + struct _IO_wide_data wd; } *new_f = (struct locked_FILE *) malloc (sizeof (struct locked_FILE)); if (new_f == NULL) @@ -46,7 +47,7 @@ _IO_new_fopen (filename, mode) #ifdef _IO_MTSAFE_IO new_f->fp.file._lock = &new_f->lock; #endif - _IO_init (&new_f->fp.file, 0); + _IO_no_init (&new_f->fp.file, 0, 0, &new_f->wd, &_IO_wfile_jumps); _IO_JUMPS (&new_f->fp) = &_IO_file_jumps; _IO_file_init (&new_f->fp.file); #if !_IO_UNIFIED_JUMPTABLES diff --git a/libio/iofopen64.c b/libio/iofopen64.c index b071a0e160..0dc19b2e1b 100644 --- a/libio/iofopen64.c +++ b/libio/iofopen64.c @@ -40,6 +40,7 @@ _IO_fopen64 (filename, mode) #ifdef _IO_MTSAFE_IO _IO_lock_t lock; #endif + struct _IO_wide_data wd; } *new_f = (struct locked_FILE *) malloc (sizeof (struct locked_FILE)); if (new_f == NULL) @@ -47,7 +48,7 @@ _IO_fopen64 (filename, mode) #ifdef _IO_MTSAFE_IO new_f->fp.file._lock = &new_f->lock; #endif - _IO_init (&new_f->fp.file, 0); + _IO_no_init (&new_f->fp.file, 0, 0, &new_f->wd, &_IO_wfile_jumps); _IO_JUMPS (&new_f->fp) = &_IO_file_jumps; _IO_file_init (&new_f->fp.file); #if !_IO_UNIFIED_JUMPTABLES diff --git a/libio/iofopncook.c b/libio/iofopncook.c index f26744f39d..85ea35c22e 100644 --- a/libio/iofopncook.c +++ b/libio/iofopncook.c @@ -33,8 +33,8 @@ static _IO_ssize_t _IO_cookie_read __P ((register _IO_FILE* fp, void* buf, _IO_ssize_t size)); static _IO_ssize_t _IO_cookie_write __P ((register _IO_FILE* fp, const void* buf, _IO_ssize_t size)); -static _IO_fpos64_t _IO_cookie_seek __P ((_IO_FILE *fp, _IO_off64_t offset, - int dir)); +static _IO_off64_t _IO_cookie_seek __P ((_IO_FILE *fp, _IO_off64_t offset, + int dir)); static int _IO_cookie_close __P ((_IO_FILE* fp)); @@ -66,7 +66,7 @@ _IO_cookie_write (fp, buf, size) return cfile->__io_functions.write (cfile->__cookie, buf, size); } -static _IO_fpos64_t +static _IO_off64_t _IO_cookie_seek (fp, offset, dir) _IO_FILE *fp; _IO_off64_t offset; diff --git a/libio/iofputs.c b/libio/iofputs.c index 1805387303..ed41d5a49c 100644 --- a/libio/iofputs.c +++ b/libio/iofputs.c @@ -1,4 +1,4 @@ -/* Copyright (C) 1993, 1996, 1997, 1998 Free Software Foundation, Inc. +/* Copyright (C) 1993, 1996, 1997, 1998, 1999 Free Software Foundation, Inc. This file is part of the GNU IO Library. This library is free software; you can redistribute it and/or @@ -32,13 +32,12 @@ _IO_fputs (str, fp) _IO_FILE *fp; { _IO_size_t len = strlen (str); - int result; + int result = EOF; CHECK_FILE (fp, EOF); _IO_cleanup_region_start ((void (*) __P ((void *))) _IO_funlockfile, fp); _IO_flockfile (fp); - if (_IO_sputn (fp, str, len) != len) - result = EOF; - else + if (_IO_fwide (fp, -1) == -1 + && _IO_sputn (fp, str, len) == len) result = 1; _IO_funlockfile (fp); _IO_cleanup_region_end (0); diff --git a/libio/iofputs_u.c b/libio/iofputs_u.c index dfd91aba7e..556522bad1 100644 --- a/libio/iofputs_u.c +++ b/libio/iofputs_u.c @@ -1,4 +1,4 @@ -/* Copyright (C) 1993, 1996, 1997, 1998 Free Software Foundation, Inc. +/* Copyright (C) 1993, 1996, 1997, 1998, 1999 Free Software Foundation, Inc. This file is part of the GNU IO Library. This library is free software; you can redistribute it and/or @@ -33,11 +33,9 @@ fputs_unlocked (str, fp) _IO_FILE *fp; { _IO_size_t len = strlen (str); - int result; + int result = EOF; CHECK_FILE (fp, EOF); - if (_IO_sputn (fp, str, len) != len) - result = EOF; - else + if (_IO_fwide (fp, -1) == -1 && _IO_sputn (fp, str, len) == len) result = 1; return result; } diff --git a/libio/iofputws.c b/libio/iofputws.c new file mode 100644 index 0000000000..daad1b9836 --- /dev/null +++ b/libio/iofputws.c @@ -0,0 +1,45 @@ +/* Copyright (C) 1993, 1996, 1997, 1998, 1999 Free Software Foundation, Inc. + This file is part of the GNU IO Library. + + This library is free software; you can redistribute it and/or + modify it under the terms of the GNU General Public License as + published by the Free Software Foundation; either version 2, or (at + your option) any later version. + + This library is distributed in the hope that it will be useful, but + WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this library; see the file COPYING. If not, write to + the Free Software Foundation, 59 Temple Place - Suite 330, Boston, + MA 02111-1307, USA. + + As a special exception, if you link this library with files + compiled with a GNU compiler to produce an executable, this does + not cause the resulting executable to be covered by the GNU General + Public License. This exception does not however invalidate any + other reasons why the executable file might be covered by the GNU + General Public License. */ + +#include "libioP.h" +#include <wchar.h> + +int +fputws (str, fp) + const wchar_t *str; + _IO_FILE *fp; +{ + _IO_size_t len = wcslen (str); + int result = EOF; + CHECK_FILE (fp, EOF); + _IO_cleanup_region_start ((void (*) __P ((void *))) _IO_funlockfile, fp); + _IO_flockfile (fp); + if (_IO_fwide (fp, 1) == 1 + && _IO_sputn (fp, (char *) str, len) == len) + result = 1; + _IO_funlockfile (fp); + _IO_cleanup_region_end (0); + return result; +} diff --git a/libio/iofputws_u.c b/libio/iofputws_u.c new file mode 100644 index 0000000000..a5749cdbec --- /dev/null +++ b/libio/iofputws_u.c @@ -0,0 +1,42 @@ +/* Copyright (C) 1993, 1996, 1997, 1998, 1999 Free Software Foundation, Inc. + This file is part of the GNU IO Library. + + This library is free software; you can redistribute it and/or + modify it under the terms of the GNU General Public License as + published by the Free Software Foundation; either version 2, or (at + your option) any later version. + + This library is distributed in the hope that it will be useful, but + WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this library; see the file COPYING. If not, write to + the Free Software Foundation, 59 Temple Place - Suite 330, Boston, + MA 02111-1307, USA. + + As a special exception, if you link this library with files + compiled with a GNU compiler to produce an executable, this does + not cause the resulting executable to be covered by the GNU General + Public License. This exception does not however invalidate any + other reasons why the executable file might be covered by the GNU + General Public License. */ + +#include "libioP.h" +#include <stdio.h> +#include <wchar.h> + +int +fputws_unlocked (str, fp) + const wchar_t *str; + _IO_FILE *fp; +{ + _IO_size_t len = wcslen (str); + int result = EOF; + CHECK_FILE (fp, EOF); + if (_IO_fwide (fp, 1) == 1 + && _IO_sputn (fp, (char *) str, len) == len) + result = 1; + return result; +} diff --git a/libio/iofsetpos.c b/libio/iofsetpos.c index cbf77347e7..bd49c13a83 100644 --- a/libio/iofsetpos.c +++ b/libio/iofsetpos.c @@ -1,4 +1,4 @@ -/* Copyright (C) 1993, 1995, 1997, 1998 Free Software Foundation, Inc. +/* Copyright (C) 1993, 1995, 1997, 1998, 1999 Free Software Foundation, Inc. This file is part of the GNU IO Library. This library is free software; you can redistribute it and/or @@ -27,7 +27,7 @@ #include <errno.h> int -_IO_fsetpos (fp, posp) +_IO_new_fsetpos (fp, posp) _IO_FILE *fp; const _IO_fpos_t *posp; { @@ -35,7 +35,7 @@ _IO_fsetpos (fp, posp) CHECK_FILE (fp, EOF); _IO_cleanup_region_start ((void (*) __P ((void *))) _IO_funlockfile, fp); _IO_flockfile (fp); - if (_IO_seekpos (fp, *posp, _IOS_INPUT|_IOS_OUTPUT) == _IO_pos_BAD) + if (_IO_seekpos (fp, posp->__pos, _IOS_INPUT|_IOS_OUTPUT) == _IO_pos_BAD) { /* ANSI explicitly requires setting errno to a positive value on failure. */ @@ -46,12 +46,20 @@ _IO_fsetpos (fp, posp) result = EOF; } else - result = 0; + { + result = 0; + if (fp->_mode > 0 + && (*fp->_codecvt->__codecvt_do_encoding) (fp->_codecvt) < 0) + /* This is a stateful encoding, restore the state. */ + fp->_wide_data->_IO_state = posp->__state; + } _IO_funlockfile (fp); _IO_cleanup_region_end (0); return result; } #ifdef weak_alias -weak_alias (_IO_fsetpos, fsetpos) +default_symbol_version (_IO_new_fsetpos, _IO_fsetpos, GLIBC_2.2); +strong_alias (_IO_new_fsetpos, __new_fsetpos) +default_symbol_version (__new_fsetpos, fsetpos, GLIBC_2.2); #endif diff --git a/libio/iofsetpos64.c b/libio/iofsetpos64.c index 13ce0fb3cb..a70d5e215a 100644 --- a/libio/iofsetpos64.c +++ b/libio/iofsetpos64.c @@ -1,4 +1,4 @@ -/* Copyright (C) 1993, 1995, 1997, 1998 Free Software Foundation, Inc. +/* Copyright (C) 1993, 1995, 1997, 1998, 1999 Free Software Foundation, Inc. This file is part of the GNU IO Library. This library is free software; you can redistribute it and/or @@ -27,7 +27,7 @@ #include <errno.h> int -_IO_fsetpos64 (fp, posp) +_IO_new_fsetpos64 (fp, posp) _IO_FILE *fp; const _IO_fpos64_t *posp; { @@ -36,7 +36,7 @@ _IO_fsetpos64 (fp, posp) CHECK_FILE (fp, EOF); _IO_cleanup_region_start ((void (*) __P ((void *))) _IO_funlockfile, fp); _IO_flockfile (fp); - if (_IO_seekpos (fp, *posp, _IOS_INPUT|_IOS_OUTPUT) == _IO_pos_BAD) + if (_IO_seekpos (fp, posp->__pos, _IOS_INPUT|_IOS_OUTPUT) == _IO_pos_BAD) { /* ANSI explicitly requires setting errno to a positive value on failure. */ @@ -47,7 +47,13 @@ _IO_fsetpos64 (fp, posp) result = EOF; } else - result = 0; + { + result = 0; + if (fp->_mode > 0 + && (*fp->_codecvt->__codecvt_do_encoding) (fp->_codecvt) < 0) + /* This is a stateful encoding, safe the state. */ + fp->_wide_data->_IO_state = posp->__state; + } _IO_funlockfile (fp); _IO_cleanup_region_end (0); return result; @@ -58,5 +64,7 @@ _IO_fsetpos64 (fp, posp) } #ifdef weak_alias -weak_alias (_IO_fsetpos64, fsetpos64) +default_symbol_version (_IO_new_fsetpos64, _IO_fsetpos64, GLIBC_2.2); +strong_alias (_IO_new_fsetpos64, __new_fsetpos64) +default_symbol_version (__new_fsetpos64, fsetpos64, GLIBC_2.2); #endif diff --git a/libio/ioftell.c b/libio/ioftell.c index 3de1ee9c02..1f25b66c2b 100644 --- a/libio/ioftell.c +++ b/libio/ioftell.c @@ -1,4 +1,4 @@ -/* Copyright (C) 1993, 1995, 1996, 1997, 1998 Free Software Foundation, Inc. +/* Copyright (C) 1993, 95, 96, 97, 98, 99 Free Software Foundation, Inc. This file is part of the GNU IO Library. This library is free software; you can redistribute it and/or @@ -31,13 +31,19 @@ long int _IO_ftell (fp) _IO_FILE *fp; { - _IO_pos_t pos; + _IO_off_t pos; CHECK_FILE (fp, -1L); _IO_cleanup_region_start ((void (*) __P ((void *))) _IO_funlockfile, fp); _IO_flockfile (fp); pos = _IO_seekoff (fp, 0, _IO_seek_cur, 0); if (_IO_in_backup (fp)) - pos -= fp->_IO_save_end - fp->_IO_save_base; + { + if (fp->_mode < 0) + pos -= fp->_IO_save_end - fp->_IO_save_base; + else + /* XXX For now. */ + abort (); + } _IO_funlockfile (fp); _IO_cleanup_region_end (0); if (pos == _IO_pos_BAD) @@ -48,7 +54,7 @@ _IO_ftell (fp) #endif return -1L; } - return _IO_pos_as_off (pos); + return pos; } #ifdef weak_alias diff --git a/libio/iofwide.c b/libio/iofwide.c new file mode 100644 index 0000000000..853920a001 --- /dev/null +++ b/libio/iofwide.c @@ -0,0 +1,365 @@ +/* Copyright (C) 1999 Free Software Foundation, Inc. + This file is part of the GNU IO Library. + + This library is free software; you can redistribute it and/or + modify it under the terms of the GNU General Public License as + published by the Free Software Foundation; either version 2, or (at + your option) any later version. + + This library is distributed in the hope that it will be useful, but + WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this library; see the file COPYING. If not, write to + the Free Software Foundation, 59 Temple Place - Suite 330, Boston, + MA 02111-1307, USA. + + As a special exception, if you link this library with files + compiled with a GNU compiler to produce an executable, this does + not cause the resulting executable to be covered by the GNU General + Public License. This exception does not however invalidate any + other reasons why the executable file might be covered by the GNU + General Public License. */ + +#include <libioP.h> +#ifdef _LIBC +# include <wchar.h> +#endif +#include <stdlib.h> +#include <string.h> + +#ifdef _LIBC +# include <langinfo.h> +# include <locale/localeinfo.h> +# include <wcsmbs/wcsmbsload.h> +#endif + + +/* Prototypes of libio's codecvt functions. */ +static enum __codecvt_result do_out (struct _IO_codecvt *codecvt, + __mbstate_t *statep, + const wchar_t *from_start, + const wchar_t *from_end, + const wchar_t **from_stop, char *to_start, + char *to_end, char **to_stop); +static enum __codecvt_result do_unshift (struct _IO_codecvt *codecvt, + __mbstate_t *statep, char *to_start, + char *to_end, char **to_stop); +static enum __codecvt_result do_in (struct _IO_codecvt *codecvt, + __mbstate_t *statep, + const char *from_start, + const char *from_end, + const char **from_stop, wchar_t *to_start, + wchar_t *to_end, wchar_t **to_stop); +static int do_encoding (struct _IO_codecvt *codecvt); +static int do_length (struct _IO_codecvt *codecvt, __mbstate_t *statep, + const char *from_start, + const char *from_end, _IO_size_t max); +static int do_max_length (struct _IO_codecvt *codecvt); +static int do_always_noconv (struct _IO_codecvt *codecvt); + + +/* The functions used in `codecvt' for libio are always the same. */ +static struct _IO_codecvt libio_codecvt = +{ + .__codecvt_destr = NULL, /* Destructor, never used. */ + .__codecvt_do_out = do_out, + .__codecvt_do_unshift = do_unshift, + .__codecvt_do_in = do_in, + .__codecvt_do_encoding = do_encoding, + .__codecvt_do_always_noconv = do_always_noconv, + .__codecvt_do_length = do_length, + .__codecvt_do_max_length = do_max_length +}; + + +/* Return orientation of stream. If mode is nonzero try to change + the orientation first. */ +#undef _IO_fwide +int +_IO_fwide (fp, mode) + _IO_FILE *fp; + int mode; +{ + /* Normalize the value. */ + mode = mode < 0 ? -1 : (mode == 0 ? 0 : 1); + + if (mode == 0 || fp->_mode != 0) + /* The caller simply wants to know about the current orientation + or the orientation already has been determined. */ + return fp->_mode; + + _IO_cleanup_region_start ((void (*) __P ((void *))) _IO_funlockfile, fp); + _IO_flockfile (fp); + + /* Set the orientation appropriately. */ + if (mode > 0) + { + fp->_wide_data->_IO_read_ptr = fp->_wide_data->_IO_read_end; + fp->_wide_data->_IO_write_ptr = fp->_wide_data->_IO_write_base; + + /* Clear the state. We start all over again. */ + memset (&fp->_wide_data->_IO_state, '\0', sizeof (__mbstate_t)); + memset (&fp->_wide_data->_IO_last_state, '\0', sizeof (__mbstate_t)); + + /* Get the character conversion functions based on the currently + selected locale for LC_CTYPE. */ +#ifdef _LIBC + { + struct gconv_fcts fcts; + struct _IO_codecvt *cc = &fp->_wide_data->_codecvt; + + __wcsmbs_clone_conv (&fcts); + + /* The functions are always the same. */ + *cc = libio_codecvt; + + cc->__cd_in.__cd.__nsteps = 1; /* Only one step allowed. */ + cc->__cd_in.__cd.__steps = fcts.towc; + + cc->__cd_in.__cd.__data[0].__invocation_counter = 0; + cc->__cd_in.__cd.__data[0].__internal_use = 1; + cc->__cd_in.__cd.__data[0].__is_last = 1; + cc->__cd_in.__cd.__data[0].__statep = &fp->_wide_data->_IO_state; + + cc->__cd_out.__cd.__nsteps = 1; /* Only one step allowed. */ + cc->__cd_out.__cd.__steps = fcts.tomb; + + cc->__cd_out.__cd.__data[0].__invocation_counter = 0; + cc->__cd_out.__cd.__data[0].__internal_use = 1; + cc->__cd_out.__cd.__data[0].__is_last = 1; + cc->__cd_out.__cd.__data[0].__statep = &fp->_wide_data->_IO_state; + } +#else +# error "somehow determine this from LC_CTYPE" +#endif + + /* From now on use the wide character callback functions. */ + ((struct _IO_FILE_plus *) fp)->vtable = fp->_wide_data->_wide_vtable; + } + + /* Set the mode now. */ + fp->_mode = mode; + + _IO_funlockfile (fp); + _IO_cleanup_region_end (0); + + return mode; +} + +#ifdef weak_alias +weak_alias (_IO_fwide, fwide) +#endif + + +static enum __codecvt_result +do_out (struct _IO_codecvt *codecvt, __mbstate_t *statep, + const wchar_t *from_start, const wchar_t *from_end, + const wchar_t **from_stop, char *to_start, char *to_end, + char **to_stop) +{ + enum __codecvt_result result; + +#ifdef _LIBC + struct __gconv_step *gs = codecvt->__cd_out.__cd.__steps; + int status; + size_t written; + const unsigned char *from_start_copy = (unsigned char *) from_start; + + codecvt->__cd_out.__cd.__data[0].__outbuf = to_start; + codecvt->__cd_out.__cd.__data[0].__outbufend = to_end; + codecvt->__cd_out.__cd.__data[0].__statep = statep; + + status = (*gs->__fct) (gs, codecvt->__cd_out.__cd.__data, &from_start_copy, + (const unsigned char *) from_end, &written, 0); + + *from_stop = (wchar_t *) from_start_copy; + *to_stop = codecvt->__cd_out.__cd.__data[0].__outbuf; + + switch (status) + { + case __GCONV_OK: + case __GCONV_EMPTY_INPUT: + result = __codecvt_ok; + break; + + case __GCONV_FULL_OUTPUT: + case __GCONV_INCOMPLETE_INPUT: + result = __codecvt_partial; + break; + + default: + result = __codecvt_error; + break; + } +#else + /* Decide what to do. */ + result = __codecvt_error; +#endif + + return result; +} + + +static enum __codecvt_result +do_unshift (struct _IO_codecvt *codecvt, __mbstate_t *statep, + char *to_start, char *to_end, char **to_stop) +{ + enum __codecvt_result result; + +#ifdef _LIBC + struct __gconv_step *gs = codecvt->__cd_out.__cd.__steps; + int status; + size_t written; + + codecvt->__cd_out.__cd.__data[0].__outbuf = to_start; + codecvt->__cd_out.__cd.__data[0].__outbufend = to_end; + codecvt->__cd_out.__cd.__data[0].__statep = statep; + + status = (*gs->__fct) (gs, codecvt->__cd_out.__cd.__data, NULL, NULL, + &written, 1); + + *to_stop = codecvt->__cd_out.__cd.__data[0].__outbuf; + + switch (status) + { + case __GCONV_OK: + case __GCONV_EMPTY_INPUT: + result = __codecvt_ok; + break; + + case __GCONV_FULL_OUTPUT: + case __GCONV_INCOMPLETE_INPUT: + result = __codecvt_partial; + break; + + default: + result = __codecvt_error; + break; + } +#else + /* Decide what to do. */ + result = __codecvt_error; +#endif + + return result; +} + + +static enum __codecvt_result +do_in (struct _IO_codecvt *codecvt, __mbstate_t *statep, + const char *from_start, const char *from_end, const char **from_stop, + wchar_t *to_start, wchar_t *to_end, wchar_t **to_stop) +{ + enum __codecvt_result result; + +#ifdef _LIBC + struct __gconv_step *gs = codecvt->__cd_in.__cd.__steps; + int status; + size_t written; + const unsigned char *from_start_copy = (unsigned char *) from_start; + + codecvt->__cd_in.__cd.__data[0].__outbuf = (char *) to_start; + codecvt->__cd_in.__cd.__data[0].__outbufend = (char *) to_end; + codecvt->__cd_in.__cd.__data[0].__statep = statep; + + status = (*gs->__fct) (gs, codecvt->__cd_in.__cd.__data, &from_start_copy, + from_end, &written, 0); + + *from_stop = from_start_copy; + *to_stop = (wchar_t *) codecvt->__cd_in.__cd.__data[0].__outbuf; + + switch (status) + { + case __GCONV_OK: + case __GCONV_EMPTY_INPUT: + result = __codecvt_ok; + break; + + case __GCONV_FULL_OUTPUT: + case __GCONV_INCOMPLETE_INPUT: + result = __codecvt_partial; + break; + + default: + result = __codecvt_error; + break; + } +#else + /* Decide what to do. */ + result = __codecvt_error; +#endif + + return result; +} + + +static int +do_encoding (struct _IO_codecvt *codecvt) +{ +#ifdef _LIBC + /* See whether the encoding is stateful. */ + if (codecvt->__cd_in.__cd.__steps[0].__stateful) + return -1; + /* Fortunately not. Now determine the input bytes for the conversion + necessary for each wide character. */ + if (codecvt->__cd_in.__cd.__steps[0].__min_needed_from + != codecvt->__cd_in.__cd.__steps[0].__max_needed_from) + /* Not a constant value. */ + return 0; + + return codecvt->__cd_in.__cd.__steps[0].__min_needed_from; +#else + /* Worst case scenario. */ + return -1; +#endif +} + + +static int +do_always_noconv (struct _IO_codecvt *codecvt) +{ + return 0; +} + + +static int +do_length (struct _IO_codecvt *codecvt, __mbstate_t *statep, + const char *from_start, const char *from_end, _IO_size_t max) +{ + int result; +#ifdef _LIBC + const unsigned char *cp = (const unsigned char *) from_start; + wchar_t to_buf[max]; + struct __gconv_step *gs = codecvt->__cd_in.__cd.__steps; + int status; + size_t written; + + codecvt->__cd_in.__cd.__data[0].__outbuf = (char *) to_buf; + codecvt->__cd_in.__cd.__data[0].__outbufend = (char *) &to_buf[max]; + codecvt->__cd_in.__cd.__data[0].__statep = statep; + + status = (*gs->__fct) (gs, codecvt->__cd_in.__cd.__data, &cp, from_end, + &written, 0); + + result = cp - (const unsigned char *) from_start; +#else + /* Decide what to do. */ + result = 0; +#endif + + return result; +} + + +static int +do_max_length (struct _IO_codecvt *codecvt) +{ +#ifdef _LIBC + return codecvt->__cd_in.__cd.__steps[0].__max_needed_from; +#else + return MB_CUR_MAX; +#endif +} diff --git a/libio/iofwrite.c b/libio/iofwrite.c index d163d29361..886de7ae35 100644 --- a/libio/iofwrite.c +++ b/libio/iofwrite.c @@ -1,4 +1,4 @@ -/* Copyright (C) 1993, 1996, 1997, 1998 Free Software Foundation, Inc. +/* Copyright (C) 1993, 1996, 1997, 1998, 1999 Free Software Foundation, Inc. This file is part of the GNU IO Library. This library is free software; you can redistribute it and/or @@ -33,7 +33,7 @@ _IO_fwrite (buf, size, count, fp) _IO_FILE *fp; { _IO_size_t request = size * count; - _IO_size_t written; + _IO_size_t written = 0; CHECK_FILE (fp, 0); /* Many traditional implementations return 0 if size==0 && count > 0, but ANSI requires us to return count in this case. */ @@ -41,7 +41,8 @@ _IO_fwrite (buf, size, count, fp) return count; _IO_cleanup_region_start ((void (*) __P ((void *))) _IO_funlockfile, fp); _IO_flockfile (fp); - written = _IO_sputn (fp, (const char *) buf, request); + if (_IO_fwide (fp, -1) == -1) + written = _IO_sputn (fp, (const char *) buf, request); _IO_funlockfile (fp); _IO_cleanup_region_end (0); if (written == request) diff --git a/libio/iofwrite_u.c b/libio/iofwrite_u.c index 38d1bd08a3..acb5b2f527 100644 --- a/libio/iofwrite_u.c +++ b/libio/iofwrite_u.c @@ -1,4 +1,4 @@ -/* Copyright (C) 1993, 1996, 1997, 1998 Free Software Foundation, Inc. +/* Copyright (C) 1993, 1996, 1997, 1998, 1999 Free Software Foundation, Inc. This file is part of the GNU IO Library. This library is free software; you can redistribute it and/or @@ -36,15 +36,18 @@ fwrite_unlocked (buf, size, count, fp) _IO_FILE *fp; { _IO_size_t request = size * count; - _IO_size_t written; + _IO_size_t written = 0; CHECK_FILE (fp, 0); /* Many traditional implementations return 0 if size==0 && count > 0, but ANSI requires us to return count in this case. */ if (request == 0) return count; - written = _IO_sputn (fp, (const char *) buf, request); - if (written == request) - return count; - else - return written / size; + if (_IO_fwide (fp, -1) == -1) + { + written = _IO_sputn (fp, (const char *) buf, request); + if (written == request) + return count; + } + + return written / size; } diff --git a/libio/iogetwline.c b/libio/iogetwline.c new file mode 100644 index 0000000000..402158a4ef --- /dev/null +++ b/libio/iogetwline.c @@ -0,0 +1,120 @@ +/* Copyright (C) 1993, 1997, 1998, 1999 Free Software Foundation, Inc. + This file is part of the GNU IO Library. + + This library is free software; you can redistribute it and/or + modify it under the terms of the GNU General Public License as + published by the Free Software Foundation; either version 2, or (at + your option) any later version. + + This library is distributed in the hope that it will be useful, but + WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this library; see the file COPYING. If not, write to + the Free Software Foundation, 59 Temple Place - Suite 330, Boston, + MA 02111-1307, USA. + + As a special exception, if you link this library with files + compiled with a GNU compiler to produce an executable, this does + not cause the resulting executable to be covered by the GNU General + Public License. This exception does not however invalidate any + other reasons why the executable file might be covered by the GNU + General Public License. */ + +#include "libioP.h" +#include <string.h> +#include <wchar.h> + +#if defined _LIBC || !_G_HAVE_IO_GETLINE_INFO + +_IO_size_t +_IO_getwline (fp, buf, n, delim, extract_delim) + _IO_FILE *fp; + wchar_t *buf; + _IO_size_t n; + wint_t delim; + int extract_delim; +{ + return _IO_getwline_info (fp, buf, n, delim, extract_delim, (wint_t *) 0); +} + +/* Algorithm based on that used by Berkeley pre-4.4 fgets implementation. + + Read chars into buf (of size n), until delim is seen. + Return number of chars read (at most n). + Does not put a terminating '\0' in buf. + If extract_delim < 0, leave delimiter unread. + If extract_delim > 0, insert delim in output. */ + +_IO_size_t +_IO_getwline_info (fp, buf, n, delim, extract_delim, eof) + _IO_FILE *fp; + wchar_t *buf; + _IO_size_t n; + wint_t delim; + int extract_delim; + wint_t *eof; +{ + wchar_t *ptr = buf; + if (eof != NULL) + *eof = 0; + while (n != 0) + { + _IO_ssize_t len = (fp->_wide_data->_IO_read_end + - fp->_wide_data->_IO_read_ptr); + if (len <= 0) + { + wint_t wc = __wuflow (fp); + if (wc == WEOF) + { + if (eof) + *eof = wc; + break; + } + if (wc == delim) + { + if (extract_delim > 0) + *ptr++ = wc; + else if (extract_delim < 0) + _IO_sputbackc (fp, wc); + return ptr - buf; + if (extract_delim > 0) + ++len; + } + *ptr++ = wc; + n--; + } + else + { + wchar_t *t; + if ((_IO_size_t) len >= n) + len = n; + t = (wchar_t *) memchr ((void *) fp->_wide_data->_IO_read_ptr, + delim, len); + if (t != NULL) + { + _IO_size_t old_len = ptr - buf; + len = t - fp->_wide_data->_IO_read_ptr; + if (extract_delim >= 0) + { + ++t; + if (extract_delim > 0) + ++len; + } + memcpy ((void *) ptr, (void *) fp->_wide_data->_IO_read_ptr, + len); + fp->_wide_data->_IO_read_ptr = t; + return old_len + len; + } + memcpy ((void *) ptr, (void *) fp->_wide_data->_IO_read_ptr, len); + fp->_wide_data->_IO_read_ptr += len; + ptr += len; + n -= len; + } + } + return ptr - buf; +} + +#endif /* Defined _LIBC || !_G_HAVE_IO_GETLINE_INFO */ diff --git a/libio/iolibio.h b/libio/iolibio.h index 7b25b40212..92f25cf9f9 100644 --- a/libio/iolibio.h +++ b/libio/iolibio.h @@ -41,13 +41,15 @@ extern int _IO_sprintf __P((char *, const char*, ...)); extern int _IO_ungetc __P((int, _IO_FILE*)); extern int _IO_vsscanf __P((const char *, const char *, _IO_va_list)); extern int _IO_vsprintf __P((char*, const char*, _IO_va_list)); +extern int _IO_vswprintf __P((wchar_t*, _IO_size_t, const wchar_t*, + _IO_va_list)); struct obstack; extern int _IO_obstack_vprintf __P ((struct obstack *, const char *, _IO_va_list)); extern int _IO_obstack_printf __P ((struct obstack *, const char *, ...)); #ifndef _IO_pos_BAD -#define _IO_pos_BAD ((_IO_fpos64_t)(-1)) +#define _IO_pos_BAD ((_IO_off64_t)(-1)) #endif #define _IO_clearerr(FP) ((FP)->_flags &= ~(_IO_ERR_SEEN|_IO_EOF_SEEN)) #define _IO_fseek(__fp, __offset, __whence) \ diff --git a/libio/iopopen.c b/libio/iopopen.c index 6b2d7f5328..15c15023f7 100644 --- a/libio/iopopen.c +++ b/libio/iopopen.c @@ -101,6 +101,8 @@ struct _IO_proc_file }; typedef struct _IO_proc_file _IO_proc_file; +static struct _IO_jump_t _IO_wproc_jumps; + static struct _IO_proc_file *proc_file_chain; _IO_FILE * @@ -186,6 +188,7 @@ _IO_new_popen (command, mode) #ifdef _IO_MTSAFE_IO _IO_lock_t lock; #endif + struct _IO_wide_data wd; } *new_f; _IO_FILE *fp; @@ -196,7 +199,7 @@ _IO_new_popen (command, mode) new_f->fpx.file.file._lock = &new_f->lock; #endif fp = &new_f->fpx.file.file; - _IO_init (fp, 0); + _IO_no_init (fp, 0, 0, &new_f->wd, &_IO_wproc_jumps); _IO_JUMPS (fp) = &_IO_proc_jumps; _IO_new_file_init (fp); #if !_IO_UNIFIED_JUMPTABLES @@ -273,6 +276,29 @@ struct _IO_jump_t _IO_proc_jumps = { JUMP_INIT(imbue, _IO_default_imbue) }; +static struct _IO_jump_t _IO_wproc_jumps = { + JUMP_INIT_DUMMY, + JUMP_INIT(finish, _IO_new_file_finish), + JUMP_INIT(overflow, _IO_new_file_overflow), + JUMP_INIT(underflow, _IO_new_file_underflow), + JUMP_INIT(uflow, _IO_default_uflow), + JUMP_INIT(pbackfail, _IO_default_pbackfail), + JUMP_INIT(xsputn, _IO_new_file_xsputn), + JUMP_INIT(xsgetn, _IO_default_xsgetn), + JUMP_INIT(seekoff, _IO_new_file_seekoff), + JUMP_INIT(seekpos, _IO_default_seekpos), + JUMP_INIT(setbuf, _IO_new_file_setbuf), + JUMP_INIT(sync, _IO_new_file_sync), + JUMP_INIT(doallocate, _IO_file_doallocate), + JUMP_INIT(read, _IO_file_read), + JUMP_INIT(write, _IO_new_file_write), + JUMP_INIT(seek, _IO_file_seek), + JUMP_INIT(close, _IO_new_proc_close), + JUMP_INIT(stat, _IO_file_stat), + JUMP_INIT(showmanyc, _IO_default_showmanyc), + JUMP_INIT(imbue, _IO_default_imbue) +}; + #if defined PIC && DO_VERSIONING strong_alias (_IO_new_popen, __new_popen) default_symbol_version (_IO_new_popen, _IO_popen, GLIBC_2.1); diff --git a/libio/ioputs.c b/libio/ioputs.c index 9ed8fe60a2..954b0f294f 100644 --- a/libio/ioputs.c +++ b/libio/ioputs.c @@ -1,4 +1,4 @@ -/* Copyright (C) 1993, 1996, 1997, 1998 Free Software Foundation, Inc. +/* Copyright (C) 1993, 1996, 1997, 1998, 1999 Free Software Foundation, Inc. This file is part of the GNU IO Library. This library is free software; you can redistribute it and/or @@ -30,16 +30,17 @@ int _IO_puts (str) const char *str; { - int result; + int result = EOF; _IO_size_t len = strlen (str); _IO_cleanup_region_start ((void (*) __P ((void *))) _IO_funlockfile, _IO_stdout); _IO_flockfile (_IO_stdout); - if (_IO_sputn (_IO_stdout, str, len) == len + + if (_IO_fwide (_IO_stdout, -1) == -1 + && _IO_sputn (_IO_stdout, str, len) == len && _IO_putc_unlocked ('\n', _IO_stdout) != EOF) result = len + 1; - else - result = EOF; + _IO_funlockfile (_IO_stdout); _IO_cleanup_region_end (0); return result; diff --git a/libio/ioseekoff.c b/libio/ioseekoff.c index 4a951dd7c1..4bd1be1e95 100644 --- a/libio/ioseekoff.c +++ b/libio/ioseekoff.c @@ -1,4 +1,4 @@ -/* Copyright (C) 1993, 1997, 1998 Free Software Foundation, Inc. +/* Copyright (C) 1993, 1997, 1998, 1999 Free Software Foundation, Inc. This file is part of the GNU IO Library. This library is free software; you can redistribute it and/or @@ -24,27 +24,27 @@ General Public License. */ #include <libioP.h> -#include <errno.h> -#ifndef errno -extern int errno; -#endif -#ifndef __set_errno -# define __set_errno(Val) errno = (Val) -#endif +#include <errno.h> +#ifndef errno +extern int errno; +#endif +#ifndef __set_errno +# define __set_errno(Val) errno = (Val) +#endif -_IO_fpos64_t +_IO_off64_t _IO_seekoff (fp, offset, dir, mode) _IO_FILE *fp; _IO_off64_t offset; int dir; int mode; { - _IO_fpos64_t retval; + _IO_off64_t retval; - if (dir != _IO_seek_cur && dir != _IO_seek_set && dir != _IO_seek_end) - { - __set_errno (EINVAL); - return EOF; + if (dir != _IO_seek_cur && dir != _IO_seek_set && dir != _IO_seek_end) + { + __set_errno (EINVAL); + return EOF; } /* If we have a backup buffer, get rid of it, since the __seekoff diff --git a/libio/ioseekpos.c b/libio/ioseekpos.c index c81c333676..3e692dae82 100644 --- a/libio/ioseekpos.c +++ b/libio/ioseekpos.c @@ -1,4 +1,4 @@ -/* Copyright (C) 1993, 1997, 1998 Free Software Foundation, Inc. +/* Copyright (C) 1993, 1997, 1998, 1999 Free Software Foundation, Inc. This file is part of the GNU IO Library. This library is free software; you can redistribute it and/or @@ -25,13 +25,13 @@ #include <libioP.h> -_IO_fpos64_t +_IO_off64_t _IO_seekpos (fp, pos, mode) _IO_FILE *fp; - _IO_fpos64_t pos; + _IO_off64_t pos; int mode; { - _IO_fpos64_t retval; + _IO_off64_t retval; /* If we have a backup buffer, get rid of it, since the __seekoff callback may not know to do the right thing about it. diff --git a/libio/iosetbuffer.c b/libio/iosetbuffer.c index d615da570c..d119cd0032 100644 --- a/libio/iosetbuffer.c +++ b/libio/iosetbuffer.c @@ -1,4 +1,4 @@ -/* Copyright (C) 1993, 1995, 1996, 1997, 1998 Free Software Foundation, Inc. +/* Copyright (C) 1993, 95, 96, 97, 98, 99 Free Software Foundation, Inc. This file is part of the GNU IO Library. This library is free software; you can redistribute it and/or @@ -38,6 +38,9 @@ _IO_setbuffer (fp, buf, size) if (!buf) size = 0; (void) _IO_SETBUF (fp, buf, size); + if (fp->_mode == 0) + /* We also have to set the buffer using the wide char function. */ + (*fp->_wide_data->_wide_vtable->__setbuf) (fp, buf, size); _IO_funlockfile (fp); _IO_cleanup_region_end (0); } diff --git a/libio/iosetvbuf.c b/libio/iosetvbuf.c index 02f4eefb5e..b9ef31a278 100644 --- a/libio/iosetvbuf.c +++ b/libio/iosetvbuf.c @@ -1,4 +1,4 @@ -/* Copyright (C) 1993, 1996, 1997, 1998 Free Software Foundation, Inc. +/* Copyright (C) 1993, 1996, 1997, 1998, 1999 Free Software Foundation, Inc. This file is part of the GNU IO Library. This library is free software; you can redistribute it and/or @@ -90,6 +90,10 @@ _IO_setvbuf (fp, buf, mode, size) goto unlock_return; } result = _IO_SETBUF (fp, buf, size) == NULL ? EOF : 0; + if (result == 0 && fp->_mode > 0) + /* We also have to set the buffer using the wide char function. */ + result = ((*fp->_wide_data->_wide_vtable->__setbuf) (fp, buf, size) == NULL + ? EOF : 0); unlock_return: _IO_funlockfile (fp); _IO_cleanup_region_end (0); diff --git a/libio/ioungetwc.c b/libio/ioungetwc.c new file mode 100644 index 0000000000..88b4162c32 --- /dev/null +++ b/libio/ioungetwc.c @@ -0,0 +1,44 @@ +/* Copyright (C) 1993, 1996, 1997, 1998, 1999 Free Software Foundation, Inc. + This file is part of the GNU IO Library. + + This library is free software; you can redistribute it and/or + modify it under the terms of the GNU General Public License as + published by the Free Software Foundation; either version 2, or (at + your option) any later version. + + This library is distributed in the hope that it will be useful, but + WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this library; see the file COPYING. If not, write to + the Free Software Foundation, 59 Temple Place - Suite 330, Boston, + MA 02111-1307, USA. + + As a special exception, if you link this library with files + compiled with a GNU compiler to produce an executable, this does + not cause the resulting executable to be covered by the GNU General + Public License. This exception does not however invalidate any + other reasons why the executable file might be covered by the GNU + General Public License. */ + +#include "libioP.h" +#include <wchar.h> + +wint_t +ungetwc (c, fp) + wint_t c; + _IO_FILE *fp; +{ + int result; + CHECK_FILE (fp, WEOF); + if (c == WEOF) + return WEOF; + _IO_cleanup_region_start ((void (*) __P ((void *))) _IO_funlockfile, fp); + _IO_flockfile (fp); + result = _IO_sputbackwc (fp, c); + _IO_funlockfile (fp); + _IO_cleanup_region_end (0); + return result; +} diff --git a/libio/iovdprintf.c b/libio/iovdprintf.c index d95af4742f..b951006975 100644 --- a/libio/iovdprintf.c +++ b/libio/iovdprintf.c @@ -1,4 +1,4 @@ -/* Copyright (C) 1995, 1997, 1998 Free Software Foundation, Inc. +/* Copyright (C) 1995, 1997, 1998, 1999 Free Software Foundation, Inc. This file is part of the GNU IO Library. This library is free software; you can redistribute it and/or @@ -36,12 +36,13 @@ _IO_vdprintf (d, format, arg) #ifdef _IO_MTSAFE_IO _IO_lock_t lock; #endif + struct _IO_wide_data wd; int done; #ifdef _IO_MTSAFE_IO tmpfil.file._lock = &lock; #endif - _IO_init (&tmpfil.file, 0); + _IO_no_init (&tmpfil.file, 0, 0, &wd, &_IO_wfile_jumps); _IO_JUMPS (&tmpfil.file) = &_IO_file_jumps; _IO_file_init (&tmpfil.file); #if !_IO_UNIFIED_JUMPTABLES diff --git a/libio/iovsprintf.c b/libio/iovsprintf.c index a1ece2da47..84c24d8d59 100644 --- a/libio/iovsprintf.c +++ b/libio/iovsprintf.c @@ -1,4 +1,4 @@ -/* Copyright (C) 1993, 1997, 1998 Free Software Foundation, Inc. +/* Copyright (C) 1993, 1997, 1998, 1999 Free Software Foundation, Inc. This file is part of the GNU IO Library. This library is free software; you can redistribute it and/or @@ -41,7 +41,7 @@ _IO_vsprintf (string, format, args) #ifdef _IO_MTSAFE_IO sf._sbf._f._lock = &lock; #endif - _IO_init (&sf._sbf._f, 0); + _IO_no_init (&sf._sbf._f, 0, -1, NULL, NULL); _IO_JUMPS (&sf._sbf._f) = &_IO_str_jumps; _IO_str_init_static (&sf._sbf._f, string, -1, string); ret = _IO_vfprintf (&sf._sbf._f, format, args); diff --git a/libio/iovsscanf.c b/libio/iovsscanf.c index 923e8290a4..2b1e44dfd8 100644 --- a/libio/iovsscanf.c +++ b/libio/iovsscanf.c @@ -1,4 +1,4 @@ -/* Copyright (C) 1993, 1997, 1998 Free Software Foundation, Inc. +/* Copyright (C) 1993, 1997, 1998, 1999 Free Software Foundation, Inc. This file is part of the GNU IO Library. This library is free software; you can redistribute it and/or @@ -38,7 +38,7 @@ _IO_vsscanf (string, format, args) _IO_lock_t lock; sf._sbf._f._lock = &lock; #endif - _IO_init (&sf._sbf._f, 0); + _IO_no_init (&sf._sbf._f, 0, -1, NULL, NULL); _IO_JUMPS (&sf._sbf._f) = &_IO_str_jumps; _IO_str_init_static (&sf._sbf._f, (char*)string, 0, NULL); ret = _IO_vfscanf (&sf._sbf._f, format, args, NULL); diff --git a/libio/iovswscanf.c b/libio/iovswscanf.c new file mode 100644 index 0000000000..f0ab62a19c --- /dev/null +++ b/libio/iovswscanf.c @@ -0,0 +1,48 @@ +/* Copyright (C) 1993, 1997, 1998, 1999 Free Software Foundation, Inc. + This file is part of the GNU IO Library. + + This library is free software; you can redistribute it and/or + modify it under the terms of the GNU General Public License as + published by the Free Software Foundation; either version 2, or (at + your option) any later version. + + This library is distributed in the hope that it will be useful, but + WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this library; see the file COPYING. If not, write to + the Free Software Foundation, 59 Temple Place - Suite 330, Boston, + MA 02111-1307, USA. + + As a special exception, if you link this library with files + compiled with a GNU compiler to produce an executable, this does + not cause the resulting executable to be covered by the GNU General + Public License. This exception does not however invalidate any + other reasons why the executable file might be covered by the GNU + General Public License. */ + +#include "libioP.h" +#include "strfile.h" +#include <wchar.h> + +int +vswscanf (string, format, args) + const wchar_t *string; + const wchar_t *format; + _IO_va_list args; +{ + int ret; + _IO_strfile sf; + struct _IO_wide_data wd; +#ifdef _IO_MTSAFE_IO + _IO_lock_t lock; + sf._sbf._f._lock = &lock; +#endif + _IO_no_init (&sf._sbf._f, 0, 1, &wd, &_IO_wstr_jumps); + _IO_JUMPS (&sf._sbf._f) = &_IO_str_jumps; + _IO_wstr_init_static (&sf._sbf._f, (wchar_t *)string, 0, NULL); + ret = _IO_vfwscanf (&sf._sbf._f, format, args, NULL); + return ret; +} diff --git a/libio/iowpadn.c b/libio/iowpadn.c new file mode 100644 index 0000000000..b4904589a2 --- /dev/null +++ b/libio/iowpadn.c @@ -0,0 +1,76 @@ +/* Copyright (C) 1993, 1997, 1999 Free Software Foundation, Inc. + This file is part of the GNU IO Library. + + This library is free software; you can redistribute it and/or + modify it under the terms of the GNU General Public License as + published by the Free Software Foundation; either version 2, or (at + your option) any later version. + + This library is distributed in the hope that it will be useful, but + WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this library; see the file COPYING. If not, write to + the Free Software Foundation, 59 Temple Place - Suite 330, Boston, + MA 02111-1307, USA. + + As a special exception, if you link this library with files + compiled with a GNU compiler to produce an executable, this does + not cause the resulting executable to be covered by the GNU General + Public License. This exception does not however invalidate any + other reasons why the executable file might be covered by the GNU + General Public License. */ + +#include "libioP.h" + +#define PADSIZE 16 +static wchar_t const blanks[PADSIZE] = +{ + L' ', L' ', L' ', L' ', L' ', L' ', L' ', L' ', + L' ', L' ', L' ', L' ', L' ', L' ', L' ', L' ' +}; +static wchar_t const zeroes[PADSIZE] = +{ + L'0', L'0', L'0', L'0', L'0', L'0', L'0', L'0', + L'0', L'0', L'0', L'0', L'0', L'0', L'0', L'0' +}; + +_IO_ssize_t +_IO_wpadn (fp, pad, count) + _IO_FILE *fp; + wint_t pad; + _IO_ssize_t count; +{ + wchar_t padbuf[PADSIZE]; + const wchar_t *padptr; + int i; + _IO_size_t written = 0; + _IO_size_t w; + + if (pad == L' ') + padptr = blanks; + else if (pad == L'0') + padptr = zeroes; + else + { + for (i = PADSIZE; --i >= 0; ) + padbuf[i] = pad; + padptr = padbuf; + } + for (i = count; i >= PADSIZE; i -= PADSIZE) + { + w = _IO_sputn (fp, (char *) padptr, PADSIZE); + written += w; + if (w != PADSIZE) + return written; + } + + if (i > 0) + { + w = _IO_sputn (fp, (char *) padptr, i); + written += w; + } + return written; +} diff --git a/libio/libio.h b/libio/libio.h index b4be610fbd..a3852886fc 100644 --- a/libio/libio.h +++ b/libio/libio.h @@ -37,10 +37,12 @@ #define _IO_off64_t _G_off64_t #define _IO_pid_t _G_pid_t #define _IO_uid_t _G_uid_t +#define _IO_iconv_t _G_iconv_t #define _IO_HAVE_SYS_WAIT _G_HAVE_SYS_WAIT #define _IO_HAVE_ST_BLKSIZE _G_HAVE_ST_BLKSIZE #define _IO_BUFSIZ _G_BUFSIZ #define _IO_va_list _G_va_list +#define _IO_wint_t _G_wint_t #ifdef _G_NEED_STDARG_H /* This define avoids name pollution if we're using GNU stdarg.h */ @@ -186,6 +188,70 @@ struct _IO_marker { #endif }; +/* This is the structure from the libstdc++ codecvt class. */ +enum __codecvt_result +{ + __codecvt_ok, + __codecvt_partial, + __codecvt_error, + __codecvt_noconv +}; + +/* The order of the elements in the following struct must match the order + of the virtual functions in the libstdc++ codecvt class. */ +struct _IO_codecvt +{ + void (*__codecvt_destr) __P ((struct _IO_codecvt *)); + enum __codecvt_result (*__codecvt_do_out) __P ((struct _IO_codecvt *, + __mbstate_t *, + const wchar_t *, + const wchar_t *, + const wchar_t **, char *, + char *, char **)); + enum __codecvt_result (*__codecvt_do_unshift) __P ((struct _IO_codecvt *, + __mbstate_t *, char *, + char *, char **)); + enum __codecvt_result (*__codecvt_do_in) __P ((struct _IO_codecvt *, + __mbstate_t *, + const char *, const char *, + const char **, wchar_t *, + wchar_t *, wchar_t **)); + int (*__codecvt_do_encoding) __P ((struct _IO_codecvt *)); + int (*__codecvt_do_always_noconv) __P ((struct _IO_codecvt *)); + int (*__codecvt_do_length) __P ((struct _IO_codecvt *, __mbstate_t *, + const char *, const char *, _IO_size_t)); + int (*__codecvt_do_max_length) __P ((struct _IO_codecvt *)); + + _IO_iconv_t __cd_in; + _IO_iconv_t __cd_out; +}; + +/* Extra data for wide character streams. */ +struct _IO_wide_data +{ + wchar_t *_IO_read_ptr; /* Current read pointer */ + wchar_t *_IO_read_end; /* End of get area. */ + wchar_t *_IO_read_base; /* Start of putback+get area. */ + wchar_t *_IO_write_base; /* Start of put area. */ + wchar_t *_IO_write_ptr; /* Current put pointer. */ + wchar_t *_IO_write_end; /* End of put area. */ + wchar_t *_IO_buf_base; /* Start of reserve area. */ + wchar_t *_IO_buf_end; /* End of reserve area. */ + /* The following fields are used to support backing up and undo. */ + wchar_t *_IO_save_base; /* Pointer to start of non-current get area. */ + wchar_t *_IO_backup_base; /* Pointer to first valid character of + backup area */ + wchar_t *_IO_save_end; /* Pointer to end of non-current get area. */ + + __mbstate_t _IO_state; + __mbstate_t _IO_last_state; + struct _IO_codecvt _codecvt; + + wchar_t _shortbuf[1]; + + struct _IO_jump_t *_wide_vtable; +}; + struct _IO_FILE { int _flags; /* High-order word is _IO_MAGIC; rest is flags. */ #define _IO_file_flags _flags @@ -231,8 +297,12 @@ struct _IO_FILE_complete #endif #if defined _G_IO_IO_FILE_VERSION && _G_IO_IO_FILE_VERSION == 0x20001 _IO_off64_t _offset; + /* Wide character stream stuff. */ + struct _IO_codecvt *_codecvt; + struct _IO_wide_data *_wide_data; + int _mode; /* Make sure we don't get into trouble again. */ - int _unused2[16]; + char _unused2[15 * sizeof (int) - 2 * sizeof (void *)]; #endif }; @@ -318,6 +388,9 @@ extern "C" { extern int __underflow __P ((_IO_FILE *)); extern int __uflow __P ((_IO_FILE *)); extern int __overflow __P ((_IO_FILE *, int)); +extern _IO_wint_t __wunderflow __P ((_IO_FILE *)); +extern _IO_wint_t __wuflow __P ((_IO_FILE *)); +extern _IO_wint_t __woverflow __P ((_IO_FILE *, _IO_wint_t)); #define _IO_getc_unlocked(_fp) \ ((_fp)->_IO_read_ptr >= (_fp)->_IO_read_end ? __uflow (_fp) \ @@ -331,16 +404,44 @@ extern int __overflow __P ((_IO_FILE *, int)); ? __overflow (_fp, (unsigned char) (_ch)) \ : (unsigned char) (*(_fp)->_IO_write_ptr++ = (_ch))) +#define _IO_getwc_unlocked(_fp) \ + ((_fp)->_wide_data->_IO_read_ptr >= (_fp)->_wide_data->_IO_read_end \ + ? __wuflow (_fp) : (_IO_wint_t) *(_fp)->_wide_data->_IO_read_ptr++) +#define _IO_putwc_unlocked(_wch, _fp) \ + ((_fp)->_wide_data->_IO_write_ptr >= (_fp)->_wide_data->_IO_write_end \ + ? __woverflow (_fp, _wch) \ + : (_IO_wint_t) (*(_fp)->_wide_data->_IO_write_ptr++ = (_wch))) + #define _IO_feof_unlocked(__fp) (((__fp)->_flags & _IO_EOF_SEEN) != 0) #define _IO_ferror_unlocked(__fp) (((__fp)->_flags & _IO_ERR_SEEN) != 0) extern int _IO_getc __P ((_IO_FILE *__fp)); extern int _IO_putc __P ((int __c, _IO_FILE *__fp)); +extern _IO_wint_t _IO_getwc __P ((_IO_FILE *__fp)); +extern _IO_wint_t _IO_putwc __P ((_IO_wint_t __wc, _IO_FILE *__fp)); extern int _IO_feof __P ((_IO_FILE *__fp)); extern int _IO_ferror __P ((_IO_FILE *__fp)); extern int _IO_peekc_locked __P ((_IO_FILE *__fp)); +extern int _IO_fwide __P ((_IO_FILE *__fp, int __mode)); +#if __GNUC__ >= 2 +/* A special optimized version of the function above. It optimizes the + case of initializing an unoriented byte stream. */ +# define _IO_fwide(__fp, __mode) \ + ({ int __result = (__mode); \ + if (__result < 0) \ + { \ + if ((__fp)->_mode == 0) \ + /* We know that all we have to do is to set the flag. */ \ + (__fp)->_mode = -1; \ + __result = (__fp)->_mode; \ + } \ + else \ + __result = _IO_fwide (__fp, __result); \ + __result; }) +#endif + /* This one is for Emacs. */ #define _IO_PENDING_OUTPUT_COUNT(_fp) \ ((_fp)->_IO_write_ptr - (_fp)->_IO_write_base) @@ -362,15 +463,22 @@ extern int _IO_ftrylockfile __P ((_IO_FILE *)); extern int _IO_vfscanf __P ((_IO_FILE * __restrict, const char * __restrict, _IO_va_list, int *__restrict)); +extern int _IO_vfwscanf __P ((_IO_FILE * __restrict, + const wchar_t * __restrict, + _IO_va_list, int *__restrict)); extern int _IO_vfprintf __P ((_IO_FILE *__restrict, const char *__restrict, _IO_va_list)); +extern int _IO_vfwprintf __P ((_IO_FILE *__restrict, const wchar_t *__restrict, + _IO_va_list)); extern _IO_ssize_t _IO_padn __P ((_IO_FILE *, int, _IO_ssize_t)); +extern _IO_ssize_t _IO_wpadn __P ((_IO_FILE *, wint_t, _IO_ssize_t)); extern _IO_size_t _IO_sgetn __P ((_IO_FILE *, void *, _IO_size_t)); -extern _IO_fpos64_t _IO_seekoff __P ((_IO_FILE *, _IO_off64_t, int, int)); -extern _IO_fpos64_t _IO_seekpos __P ((_IO_FILE *, _IO_fpos64_t, int)); +extern _IO_off64_t _IO_seekoff __P ((_IO_FILE *, _IO_off64_t, int, int)); +extern _IO_off64_t _IO_seekpos __P ((_IO_FILE *, _IO_off64_t, int)); extern void _IO_free_backup_area __P ((_IO_FILE *)); +extern void _IO_free_wbackup_area __P ((_IO_FILE *)); #ifdef __cplusplus } diff --git a/libio/libioP.h b/libio/libioP.h index a9577cec74..6ed79b7169 100644 --- a/libio/libioP.h +++ b/libio/libioP.h @@ -1,4 +1,4 @@ -/* Copyright (C) 1993, 1997, 1998 Free Software Foundation, Inc. +/* Copyright (C) 1993, 1997, 1998, 1999 Free Software Foundation, Inc. This file is part of the GNU IO Library. This library is free software; you can redistribute it and/or @@ -70,6 +70,7 @@ extern "C" { #endif #define _IO_JUMPS(THIS) ((struct _IO_FILE_plus *) (THIS))->vtable +#define _IO_WIDE_JUMPS(THIS) ((struct _IO_FILE *) (THIS))->_wide_data->_wide_vtable #if _IO_JUMPS_OFFSET # define _IO_JUMPS_FUNC(THIS) \ (*(struct _IO_jump_t **) ((void *) &((struct _IO_FILE_plus *) (THIS))->vtable\ @@ -146,8 +147,8 @@ typedef _IO_size_t (*_IO_xsgetn_t) __PMT ((_IO_FILE *FP, void *DATA, (MODE==1), or the end of the file (MODE==2). It matches the streambuf::seekoff virtual function. It is also used for the ANSI fseek function. */ -typedef _IO_fpos64_t (*_IO_seekoff_t) __PMT ((_IO_FILE *FP, _IO_off64_t OFF, - int DIR, int MODE)); +typedef _IO_off64_t (*_IO_seekoff_t) __PMT ((_IO_FILE *FP, _IO_off64_t OFF, + int DIR, int MODE)); #define _IO_SEEKOFF(FP, OFF, DIR, MODE) JUMP3 (__seekoff, FP, OFF, DIR, MODE) /* The 'seekpos' hook also moves the stream position, @@ -155,7 +156,7 @@ typedef _IO_fpos64_t (*_IO_seekoff_t) __PMT ((_IO_FILE *FP, _IO_off64_t OFF, It matches the streambuf::seekpos virtual function. It is also used for the ANSI fgetpos and fsetpos functions. */ /* The _IO_seek_cur and _IO_seek_end options are not allowed. */ -typedef _IO_fpos64_t (*_IO_seekpos_t) __PMT ((_IO_FILE *, _IO_fpos64_t, int)); +typedef _IO_off64_t (*_IO_seekpos_t) __PMT ((_IO_FILE *, _IO_off64_t, int)); #define _IO_SEEKPOS(FP, POS, FLAGS) JUMP2 (__seekpos, FP, POS, FLAGS) /* The 'setbuf' hook gives a buffer to the file. @@ -205,7 +206,7 @@ typedef _IO_ssize_t (*_IO_write_t) __PMT ((_IO_FILE *, const void *, It generalizes the Unix lseek(2) function. It matches the streambuf::sys_seek virtual function, which is specific to this implementation. */ -typedef _IO_fpos64_t (*_IO_seek_t) __PMT ((_IO_FILE *, _IO_off64_t, int)); +typedef _IO_off64_t (*_IO_seek_t) __PMT ((_IO_FILE *, _IO_off64_t, int)); #define _IO_SYSSEEK(FP, OFFSET, MODE) JUMP2 (__seek, FP, OFFSET, MODE) /* The 'sysclose' hook is used to finalize (close, finish up) an @@ -282,9 +283,6 @@ struct _IO_FILE_plus /* Generic functions */ -extern _IO_fpos64_t _IO_seekoff __P ((_IO_FILE *, _IO_off64_t, int, int)); -extern _IO_fpos64_t _IO_seekpos __P ((_IO_FILE *, _IO_fpos64_t, int)); - extern void _IO_switch_to_main_get_area __P ((_IO_FILE *)); extern void _IO_switch_to_backup_area __P ((_IO_FILE *)); extern int _IO_switch_to_get_mode __P ((_IO_FILE *)); @@ -299,56 +297,94 @@ extern void _IO_setb __P ((_IO_FILE *, char *, char *, int)); extern unsigned _IO_adjust_column __P ((unsigned, const char *, int)); #define _IO_sputn(__fp, __s, __n) _IO_XSPUTN (__fp, __s, __n) +extern void _IO_switch_to_main_wget_area __P ((_IO_FILE *)); +extern void _IO_switch_to_wbackup_area __P ((_IO_FILE *)); +extern int _IO_switch_to_wget_mode __P ((_IO_FILE *)); +extern void _IO_wsetb __P ((_IO_FILE *, wchar_t *, wchar_t *, int)); +extern wint_t _IO_sputbackwc __P ((_IO_FILE *, wint_t)); +extern wint_t _IO_sungetwc __P ((_IO_FILE *)); +extern void _IO_wdoallocbuf __P ((_IO_FILE *)); +extern void _IO_unsave_wmarkers __P ((_IO_FILE *)); +extern void _IO_wsetb __P ((_IO_FILE *, wchar_t *, wchar_t *, int)); +extern unsigned _IO_adjust_wcolumn __P ((unsigned, const wchar_t *, int)); + /* Marker-related function. */ extern void _IO_init_marker __P ((struct _IO_marker *, _IO_FILE *)); +extern void _IO_init_wmarker __P ((struct _IO_marker *, _IO_FILE *)); extern void _IO_remove_marker __P ((struct _IO_marker *)); extern int _IO_marker_difference __P ((struct _IO_marker *, struct _IO_marker *)); extern int _IO_marker_delta __P ((struct _IO_marker *)); +extern int _IO_wmarker_delta __P ((struct _IO_marker *)); extern int _IO_seekmark __P ((_IO_FILE *, struct _IO_marker *, int)); +extern int _IO_seekwmark __P ((_IO_FILE *, struct _IO_marker *, int)); /* Default jumptable functions. */ extern int _IO_default_underflow __P ((_IO_FILE *)); extern int _IO_default_uflow __P ((_IO_FILE *)); +extern wint_t _IO_wdefault_uflow __P ((_IO_FILE *)); extern int _IO_default_doallocate __P ((_IO_FILE *)); +extern int _IO_wdefault_doallocate __P ((_IO_FILE *)); extern void _IO_default_finish __P ((_IO_FILE *, int)); +extern void _IO_wdefault_finish __P ((_IO_FILE *, int)); extern int _IO_default_pbackfail __P ((_IO_FILE *, int)); +extern wint_t _IO_wdefault_pbackfail __P ((_IO_FILE *, wint_t)); extern _IO_FILE* _IO_default_setbuf __P ((_IO_FILE *, char *, _IO_ssize_t)); +extern _IO_FILE* _IO_wdefault_setbuf __P ((_IO_FILE *, wchar_t *, + _IO_ssize_t)); extern _IO_size_t _IO_default_xsputn __P ((_IO_FILE *, const void *, _IO_size_t)); +extern _IO_size_t _IO_wdefault_xsputn __P ((_IO_FILE *, const void *, + _IO_size_t)); extern _IO_size_t _IO_default_xsgetn __P ((_IO_FILE *, void *, _IO_size_t)); -extern _IO_fpos64_t _IO_default_seekoff __P ((_IO_FILE *, - _IO_off64_t, int, int)); -extern _IO_fpos64_t _IO_default_seekpos __P ((_IO_FILE *, - _IO_fpos64_t, int)); +extern _IO_size_t _IO_wdefault_xsgetn __P ((_IO_FILE *, void *, _IO_size_t)); +extern _IO_off64_t _IO_default_seekoff __P ((_IO_FILE *, + _IO_off64_t, int, int)); +extern _IO_off64_t _IO_default_seekpos __P ((_IO_FILE *, _IO_off64_t, int)); extern _IO_ssize_t _IO_default_write __P ((_IO_FILE *, const void *, _IO_ssize_t)); extern _IO_ssize_t _IO_default_read __P ((_IO_FILE *, void *, _IO_ssize_t)); extern int _IO_default_stat __P ((_IO_FILE *, void *)); -extern _IO_fpos64_t _IO_default_seek __P ((_IO_FILE *, _IO_off64_t, int)); +extern _IO_off64_t _IO_default_seek __P ((_IO_FILE *, _IO_off64_t, int)); extern int _IO_default_sync __P ((_IO_FILE *)); #define _IO_default_close ((_IO_close_t) _IO_default_sync) extern int _IO_default_showmanyc __P ((_IO_FILE *)); extern void _IO_default_imbue __P ((_IO_FILE *, void *)); extern struct _IO_jump_t _IO_file_jumps; +extern struct _IO_jump_t _IO_wfile_jumps; extern struct _IO_jump_t _IO_old_file_jumps; extern struct _IO_jump_t _IO_streambuf_jumps; extern struct _IO_jump_t _IO_proc_jumps; extern struct _IO_jump_t _IO_old_proc_jumps; extern struct _IO_jump_t _IO_str_jumps; +extern struct _IO_jump_t _IO_wstr_jumps; extern int _IO_do_write __P ((_IO_FILE *, const char *, _IO_size_t)); extern int _IO_new_do_write __P ((_IO_FILE *, const char *, _IO_size_t)); extern int _IO_old_do_write __P ((_IO_FILE *, const char *, _IO_size_t)); +extern int _IO_wdo_write __P ((_IO_FILE *, const wchar_t *, _IO_size_t)); extern int _IO_flush_all __P ((void)); extern int _IO_cleanup __P ((void)); extern void _IO_flush_all_linebuffered __P ((void)); +extern int _IO_new_fgetpos __P ((_IO_FILE *, _IO_fpos_t *)); +extern int _IO_old_fgetpos __P ((_IO_FILE *, _IO_fpos_t *)); +extern int _IO_new_fsetpos __P ((_IO_FILE *, const _IO_fpos_t *)); +extern int _IO_old_fsetpos __P ((_IO_FILE *, const _IO_fpos_t *)); +extern int _IO_new_fgetpos64 __P ((_IO_FILE *, _IO_fpos64_t *)); +extern int _IO_old_fgetpos64 __P ((_IO_FILE *, _IO_fpos64_t *)); +extern int _IO_new_fsetpos64 __P ((_IO_FILE *, const _IO_fpos64_t *)); +extern int _IO_old_fsetpos64 __P ((_IO_FILE *, const _IO_fpos64_t *)); + #define _IO_do_flush(_f) \ - _IO_do_write(_f, (_f)->_IO_write_base, \ - (_f)->_IO_write_ptr-(_f)->_IO_write_base) + ((_f)->_mode <= 0 \ + ? _IO_do_write(_f, (_f)->_IO_write_base, \ + (_f)->_IO_write_ptr-(_f)->_IO_write_base) \ + : _IO_wdo_write(_f, (_f)->_wide_data->_IO_write_base, \ + ((_f)->_wide_data->_IO_write_ptr \ + - (_f)->_wide_data->_IO_write_base))) #define _IO_old_do_flush(_f) \ _IO_old_do_write(_f, (_f)->_IO_write_base, \ (_f)->_IO_write_ptr-(_f)->_IO_write_base) @@ -357,18 +393,29 @@ extern void _IO_flush_all_linebuffered __P ((void)); ((fp)->_flags = ((fp)->_flags & ~(mask)) | ((f) & (mask))) #define _IO_setg(fp, eb, g, eg) ((fp)->_IO_read_base = (eb),\ (fp)->_IO_read_ptr = (g), (fp)->_IO_read_end = (eg)) +#define _IO_wsetg(fp, eb, g, eg) ((fp)->_wide_data->_IO_read_base = (eb),\ + (fp)->_wide_data->_IO_read_ptr = (g), \ + (fp)->_wide_data->_IO_read_end = (eg)) #define _IO_setp(__fp, __p, __ep) \ - ((__fp)->_IO_write_base = (__fp)->_IO_write_ptr = __p, (__fp)->_IO_write_end = (__ep)) + ((__fp)->_IO_write_base = (__fp)->_IO_write_ptr \ + = __p, (__fp)->_IO_write_end = (__ep)) +#define _IO_wsetp(__fp, __p, __ep) \ + ((__fp)->_wide_data->_IO_write_base \ + = (__fp)->_wide_data->_IO_write_ptr = __p, \ + (__fp)->_wide_data->_IO_write_end = (__ep)) #define _IO_have_backup(fp) ((fp)->_IO_save_base != NULL) +#define _IO_have_wbackup(fp) ((fp)->_wide_data->_IO_save_base != NULL) #define _IO_in_backup(fp) ((fp)->_flags & _IO_IN_BACKUP) #define _IO_have_markers(fp) ((fp)->_markers != NULL) #define _IO_blen(fp) ((fp)->_IO_buf_end - (fp)->_IO_buf_base) +#define _IO_wblen(fp) ((fp)->_wide_data->_IO_buf_end \ + - (fp)->_wide_data->_IO_buf_base) /* Jumptable functions for files. */ extern int _IO_file_doallocate __P ((_IO_FILE *)); extern _IO_FILE* _IO_file_setbuf __P ((_IO_FILE *, char *, _IO_ssize_t)); -extern _IO_fpos64_t _IO_file_seekoff __P ((_IO_FILE *, _IO_off64_t, int, int)); +extern _IO_off64_t _IO_file_seekoff __P ((_IO_FILE *, _IO_off64_t, int, int)); extern _IO_size_t _IO_file_xsputn __P ((_IO_FILE *, const void *, _IO_size_t)); extern _IO_size_t _IO_file_xsgetn __P ((_IO_FILE *, void *, _IO_size_t)); extern int _IO_file_stat __P ((_IO_FILE *, void *)); @@ -387,7 +434,7 @@ extern _IO_ssize_t _IO_file_write __P ((_IO_FILE *, const void *, extern _IO_ssize_t _IO_file_read __P ((_IO_FILE *, void *, _IO_ssize_t)); extern int _IO_file_sync __P ((_IO_FILE *)); extern int _IO_file_close_it __P ((_IO_FILE *)); -extern _IO_fpos64_t _IO_file_seek __P ((_IO_FILE *, _IO_off64_t, int)); +extern _IO_off64_t _IO_file_seek __P ((_IO_FILE *, _IO_off64_t, int)); extern void _IO_file_finish __P ((_IO_FILE *, int)); extern _IO_FILE* _IO_new_file_attach __P ((_IO_FILE *, int)); @@ -395,19 +442,21 @@ extern int _IO_new_file_close_it __P ((_IO_FILE *)); extern void _IO_new_file_finish __P ((_IO_FILE *, int)); extern _IO_FILE* _IO_new_file_fopen __P ((_IO_FILE *, const char *, const char *, int)); +extern void _IO_no_init __P ((_IO_FILE *, int, int, struct _IO_wide_data *, + struct _IO_jump_t *)); extern void _IO_new_file_init __P ((_IO_FILE *)); extern _IO_FILE* _IO_new_file_setbuf __P ((_IO_FILE *, char *, _IO_ssize_t)); extern int _IO_new_file_sync __P ((_IO_FILE *)); extern int _IO_new_file_underflow __P ((_IO_FILE *)); extern int _IO_new_file_overflow __P ((_IO_FILE *, int)); -extern _IO_fpos64_t _IO_new_file_seekoff __P ((_IO_FILE *, _IO_off64_t, int, int)); +extern _IO_off64_t _IO_new_file_seekoff __P ((_IO_FILE *, _IO_off64_t, int, int)); extern _IO_ssize_t _IO_new_file_write __P ((_IO_FILE *, const void *, _IO_ssize_t)); extern _IO_size_t _IO_new_file_xsputn __P ((_IO_FILE *, const void *, _IO_size_t)); extern _IO_FILE* _IO_old_file_setbuf __P ((_IO_FILE *, char *, _IO_ssize_t)); -extern _IO_fpos64_t _IO_old_file_seekoff __P ((_IO_FILE *, _IO_off64_t, int, - int)); +extern _IO_off64_t _IO_old_file_seekoff __P ((_IO_FILE *, _IO_off64_t, int, + int)); extern _IO_size_t _IO_old_file_xsputn __P ((_IO_FILE *, const void *, _IO_size_t)); extern int _IO_old_file_underflow __P ((_IO_FILE *)); @@ -422,6 +471,15 @@ extern int _IO_old_file_sync __P ((_IO_FILE *)); extern int _IO_old_file_close_it __P ((_IO_FILE *)); extern void _IO_old_file_finish __P ((_IO_FILE *, int)); +extern int _IO_wfile_doallocate __P ((_IO_FILE *)); +extern _IO_size_t _IO_wfile_xsputn __P ((_IO_FILE *, const void *, + _IO_size_t)); +extern _IO_FILE* _IO_wfile_setbuf __P ((_IO_FILE *, wchar_t *, _IO_ssize_t)); +extern wint_t _IO_wfile_sync __P ((_IO_FILE *)); +extern wint_t _IO_wfile_underflow __P ((_IO_FILE *)); +extern wint_t _IO_wfile_overflow __P ((_IO_FILE *, wint_t)); +extern _IO_off64_t _IO_wfile_seekoff __P ((_IO_FILE *, _IO_off64_t, int, int)); + /* Jumptable functions for proc_files. */ extern _IO_FILE* _IO_proc_open __P ((_IO_FILE *, const char *, const char *)); extern _IO_FILE* _IO_new_proc_open __P ((_IO_FILE *, const char *, const char *)); @@ -434,7 +492,7 @@ extern int _IO_old_proc_close __P ((_IO_FILE *)); extern int _IO_str_underflow __P ((_IO_FILE *)); extern int _IO_str_overflow __P ((_IO_FILE *, int)); extern int _IO_str_pbackfail __P ((_IO_FILE *, int)); -extern _IO_fpos64_t _IO_str_seekoff __P ((_IO_FILE *, _IO_off64_t, int, int)); +extern _IO_off64_t _IO_str_seekoff __P ((_IO_FILE *, _IO_off64_t, int, int)); extern void _IO_str_finish __P ((_IO_FILE *, int)); /* Other strfile functions */ @@ -442,6 +500,16 @@ extern void _IO_str_init_static __P ((_IO_FILE *, char *, int, char *)); extern void _IO_str_init_readonly __P ((_IO_FILE *, const char *, int)); extern _IO_ssize_t _IO_str_count __P ((_IO_FILE *)); +/* And the wide character versions. */ +extern void _IO_wstr_init_static __P ((_IO_FILE *, wchar_t *, int, wchar_t *)); +extern void _IO_wstr_init_readonly __P ((_IO_FILE *, const char *, int)); +extern _IO_ssize_t _IO_wstr_count __P ((_IO_FILE *)); +extern _IO_wint_t _IO_wstr_overflow __P ((_IO_FILE *, _IO_wint_t)); +extern _IO_wint_t _IO_wstr_underflow __P ((_IO_FILE *)); +extern _IO_off64_t _IO_wstr_seekoff __P ((_IO_FILE *, _IO_off64_t, int, int)); +extern _IO_wint_t _IO_wstr_pbackfail __P ((_IO_FILE *, _IO_wint_t)); +extern void _IO_wstr_finish __P ((_IO_FILE *, int)); + extern int _IO_vasprintf __P ((char **result_ptr, __const char *format, _IO_va_list args)); extern int _IO_vdprintf __P ((int d, __const char *format, _IO_va_list arg)); @@ -453,6 +521,10 @@ extern _IO_size_t _IO_getline __P ((_IO_FILE *,char *, _IO_size_t, int, int)); extern _IO_size_t _IO_getline_info __P ((_IO_FILE *,char *, _IO_size_t, int, int, int *)); extern _IO_ssize_t _IO_getdelim __P ((char **, _IO_size_t *, int, _IO_FILE *)); +extern _IO_size_t _IO_getwline __P ((_IO_FILE *,wchar_t *, _IO_size_t, wint_t, + int)); +extern _IO_size_t _IO_getwline_info __P ((_IO_FILE *,wchar_t *, _IO_size_t, + wint_t, int, wint_t *)); extern double _IO_strtod __P ((const char *, char **)); extern char *_IO_dtoa __P ((double __d, int __mode, int __ndigits, int *__decpt, int *__sign, char **__rve)); @@ -516,7 +588,15 @@ extern void (*_IO_cleanup_registration_needed) __PMT ((void)); (_B) = (char *) mmap (0, ROUND_TO_PAGE (_S), \ PROT_READ | PROT_WRITE, \ MAP_PRIVATE | MAP_ANONYMOUS, -1, 0); \ - if ((_B) == (char *) -1) \ + if ((_B) == (char *) MAP_FAILED) \ + return (_R); \ + } while (0) +# define ALLOC_WBUF(_B, _S, _R) \ + do { \ + (_B) = (wchar_t *) mmap (0, ROUND_TO_PAGE (_S), \ + PROT_READ | PROT_WRITE, \ + MAP_PRIVATE | MAP_ANONYMOUS, -1, 0); \ + if ((_B) == (wchar_t *) MAP_FAILED) \ return (_R); \ } while (0) @@ -544,26 +624,17 @@ extern int _IO_close __P ((int)); extern int _IO_fstat __P ((int, struct stat *)); extern int _IO_vscanf __P ((const char *, _IO_va_list)); -/* Operations on _IO_fpos64_t. - Normally, these are trivial, but we provide hooks for configurations - where an _IO_fpos64_t is a struct. - Note that _IO_off64_t must be an integral type. */ - -/* _IO_pos_BAD is an _IO_fpos64_t value indicating error, unknown, or EOF. */ +/* _IO_pos_BAD is an _IO_off64_t value indicating error, unknown, or EOF. */ #ifndef _IO_pos_BAD -# define _IO_pos_BAD ((_IO_fpos64_t) -1) +# define _IO_pos_BAD ((_IO_off64_t) -1) #endif -/* _IO_pos_as_off converts an _IO_fpos64_t value to an _IO_off64_t value. */ -#ifndef _IO_pos_as_off -# define _IO_pos_as_off(__pos) ((_IO_off64_t) (__pos)) -#endif -/* _IO_pos_adjust adjust an _IO_fpos64_t by some number of bytes. */ +/* _IO_pos_adjust adjust an _IO_off64_t by some number of bytes. */ #ifndef _IO_pos_adjust -# define _IO_pos_adjust(__pos, __delta) ((__pos) += (__delta)) +# define _IO_pos_adjust(pos, delta) ((pos) += (delta)) #endif -/* _IO_pos_0 is an _IO_fpos64_t value indicating beginning of file. */ +/* _IO_pos_0 is an _IO_off64_t value indicating beginning of file. */ #ifndef _IO_pos_0 -# define _IO_pos_0 ((_IO_fpos64_t) 0) +# define _IO_pos_0 ((_IO_off64_t) 0) #endif #ifdef __cplusplus @@ -573,15 +644,16 @@ extern int _IO_vscanf __P ((const char *, _IO_va_list)); #ifdef _IO_MTSAFE_IO /* check following! */ # ifdef _IO_USE_OLD_IO_FILE -# define FILEBUF_LITERAL(CHAIN, FLAGS, FD) \ +# define FILEBUF_LITERAL(CHAIN, FLAGS, FD, WDP) \ { _IO_MAGIC+_IO_LINKED+_IO_IS_FILEBUF+FLAGS, \ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, CHAIN, FD, \ 0, _IO_pos_BAD, 0, 0, { 0 }, &_IO_stdfile_##FD##_lock } # else -# define FILEBUF_LITERAL(CHAIN, FLAGS, FD) \ +# define FILEBUF_LITERAL(CHAIN, FLAGS, FD, WDP) \ { _IO_MAGIC+_IO_LINKED+_IO_IS_FILEBUF+FLAGS, \ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, CHAIN, FD, \ - 0, _IO_pos_BAD, 0, 0, { 0 }, &_IO_stdfile_##FD##_lock, _IO_pos_BAD } + 0, _IO_pos_BAD, 0, 0, { 0 }, &_IO_stdfile_##FD##_lock, _IO_pos_BAD,\ + NULL, WDP, 0 } # endif #else # ifdef _IO_USE_OLD_IO_FILE @@ -592,7 +664,8 @@ extern int _IO_vscanf __P ((const char *, _IO_va_list)); # define FILEBUF_LITERAL(CHAIN, FLAGS, FD) \ { _IO_MAGIC+_IO_LINKED+_IO_IS_FILEBUF+FLAGS, \ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, CHAIN, FD, \ - 0, _IO_pos_BAD, 0, 0, { 0 }, 0, _IO_pos_BAD } + 0, _IO_pos_BAD, 0, 0, { 0 }, 0, _IO_pos_BAD, \ + NULL, WDP, 0 } # endif #endif diff --git a/libio/memstream.c b/libio/memstream.c index 71aab2f6ea..840d0e6968 100644 --- a/libio/memstream.c +++ b/libio/memstream.c @@ -1,4 +1,4 @@ -/* Copyright (C) 1995, 1996, 1997 Free Software Foundation, Inc. +/* Copyright (C) 1995, 1996, 1997, 1999 Free Software Foundation, Inc. This file is part of the GNU C Library. The GNU C Library is free software; you can redistribute it and/or @@ -32,9 +32,11 @@ struct _IO_FILE_memstream static int _IO_mem_sync __P ((_IO_FILE* fp)); static void _IO_mem_finish __P ((_IO_FILE* fp, int)); +static int _IO_wmem_sync __P ((_IO_FILE* fp)); +static void _IO_wmem_finish __P ((_IO_FILE* fp, int)); -static const struct _IO_jump_t _IO_mem_jumps = +static struct _IO_jump_t _IO_mem_jumps = { JUMP_INIT_DUMMY, JUMP_INIT (finish, _IO_mem_finish), @@ -58,6 +60,30 @@ static const struct _IO_jump_t _IO_mem_jumps = JUMP_INIT(imbue, _IO_default_imbue) }; +static struct _IO_jump_t _IO_wmem_jumps = +{ + JUMP_INIT_DUMMY, + JUMP_INIT (finish, (_IO_finish_t) _IO_wmem_finish), + JUMP_INIT (overflow, (_IO_overflow_t) _IO_wstr_overflow), + JUMP_INIT (underflow, (_IO_underflow_t) _IO_wstr_underflow), + JUMP_INIT (uflow, (_IO_underflow_t) _IO_wdefault_uflow), + JUMP_INIT (pbackfail, (_IO_pbackfail_t) _IO_wstr_pbackfail), + JUMP_INIT (xsputn, (_IO_xsputn_t) _IO_wdefault_xsputn), + JUMP_INIT (xsgetn, (_IO_xsgetn_t) _IO_wdefault_xsgetn), + JUMP_INIT (seekoff, _IO_wstr_seekoff), + JUMP_INIT (seekpos, _IO_default_seekpos), + JUMP_INIT (setbuf, (_IO_setbuf_t) _IO_wdefault_setbuf), + JUMP_INIT (sync, (_IO_sync_t) _IO_wmem_sync), + JUMP_INIT (doallocate, _IO_wdefault_doallocate), + JUMP_INIT (read, _IO_default_read), + JUMP_INIT (write, _IO_default_write), + JUMP_INIT (seek, _IO_default_seek), + JUMP_INIT (close, _IO_default_close), + JUMP_INIT (stat, _IO_default_stat), + JUMP_INIT(showmanyc, _IO_default_showmanyc), + JUMP_INIT(imbue, _IO_default_imbue) +}; + /* Open a stream that writes into a malloc'd buffer that is expanded as necessary. *BUFLOC and *SIZELOC are updated with the buffer's location and the number of characters written on fflush or fclose. */ @@ -72,6 +98,7 @@ open_memstream (bufloc, sizeloc) #ifdef _IO_MTSAFE_IO _IO_lock_t lock; #endif + struct _IO_wide_data wd; } *new_f; char *buf; @@ -85,7 +112,7 @@ open_memstream (bufloc, sizeloc) buf = malloc (_IO_BUFSIZ); if (buf == NULL) return NULL; - _IO_init (&new_f->fp._sf._sbf._f, 0); + _IO_no_init (&new_f->fp._sf._sbf._f, 0, 0, &new_f->wd, &_IO_wmem_jumps); _IO_JUMPS (&new_f->fp._sf._sbf._f) = &_IO_mem_jumps; _IO_str_init_static (&new_f->fp._sf._sbf._f, buf, _IO_BUFSIZ, buf); new_f->fp._sf._sbf._f._flags &= ~_IO_USER_BUF; @@ -144,3 +171,55 @@ _IO_mem_finish (fp, dummy) _IO_default_finish (fp, 0); } + + +static int +_IO_wmem_sync (fp) + _IO_FILE* fp; +{ + struct _IO_FILE_memstream *mp = (struct _IO_FILE_memstream *) fp; + int res; + + res = _IO_default_sync (fp); + if (res < 0) + return res; + + if (fp->_wide_data->_IO_write_ptr == fp->_wide_data->_IO_write_end) + { + _IO_wstr_overflow (fp, L'\0'); + --fp->_wide_data->_IO_write_ptr; + } + else + *fp->_wide_data->_IO_write_ptr = '\0'; + + *mp->bufloc = (char *) fp->_wide_data->_IO_write_base; + *mp->sizeloc = (fp->_wide_data->_IO_write_ptr + - fp->_wide_data->_IO_write_base); + + return 0; +} + + +static void +_IO_wmem_finish (fp, dummy) + _IO_FILE* fp; + int dummy; +{ + struct _IO_FILE_memstream *mp = (struct _IO_FILE_memstream *) fp; + + *mp->bufloc = (char *) realloc (fp->_wide_data->_IO_write_base, + (fp->_wide_data->_IO_write_ptr + - fp->_wide_data->_IO_write_base + 1) + * sizeof (wchar_t)); + if (*mp->bufloc != NULL) + { + ((wchar_t *) (*mp->bufloc))[fp->_wide_data->_IO_write_ptr + - fp->_wide_data->_IO_write_base] = '\0'; + *mp->sizeloc = (fp->_wide_data->_IO_write_ptr + - fp->_wide_data->_IO_write_base); + } + + fp->_wide_data->_IO_buf_base = NULL; + + _IO_default_finish (fp, 0); +} diff --git a/libio/obprintf.c b/libio/obprintf.c index 0e947b25ad..29e09d4281 100644 --- a/libio/obprintf.c +++ b/libio/obprintf.c @@ -127,11 +127,11 @@ _IO_obstack_vprintf (struct obstack *obstack, const char *format, va_list args) new_f.ofile.file.file._lock = &new_f.lock; #endif - _IO_init (&new_f.ofile.file.file, 0); - _IO_JUMPS (&new_f.ofile.file.file) = &_IO_obstack_jumps; + _IO_no_init (&new_f.ofile.file.file, 0, -1, NULL, NULL); + _IO_JUMPS (&new_f.ofile.file) = &_IO_obstack_jumps; _IO_str_init_static (&new_f.ofile.file.file, obstack_base (obstack), - obstack_object_size (obstack) + obstack_room (obstack), - obstack_next_free (obstack)); + (obstack_object_size (obstack) + + obstack_room (obstack)), obstack_next_free (obstack)); /* Now allocate the rest of the current chunk. */ obstack_blank_fast (obstack, (new_f.ofile.file.file._IO_write_end diff --git a/libio/oldfileops.c b/libio/oldfileops.c index fe29a7965b..d65c272d48 100644 --- a/libio/oldfileops.c +++ b/libio/oldfileops.c @@ -285,7 +285,7 @@ old_do_write (fp, data, to_do) fp->_old_offset = _IO_pos_BAD; else if (fp->_IO_read_end != fp->_IO_write_base) { - _IO_pos_t new_pos + _IO_off_t new_pos = _IO_SYSSEEK (fp, fp->_IO_write_base - fp->_IO_read_end, 1); if (new_pos == _IO_pos_BAD) return 0; @@ -449,14 +449,14 @@ _IO_old_file_sync (fp) return retval; } -_IO_fpos64_t +_IO_off64_t _IO_old_file_seekoff (fp, offset, dir, mode) _IO_FILE *fp; _IO_off64_t offset; int dir; int mode; { - _IO_pos_t result; + _IO_off_t result; _IO_off64_t delta, new_offset; long count; /* POSIX.1 8.2.3.7 says that after a call the fflush() the file @@ -500,7 +500,7 @@ _IO_old_file_seekoff (fp, offset, dir, mode) if (fp->_old_offset == _IO_pos_BAD) goto dumb; /* Make offset absolute, assuming current pointer is file_ptr(). */ - offset += _IO_pos_as_off (fp->_old_offset); + offset += fp->_old_offset; dir = _IO_seek_set; break; @@ -529,7 +529,7 @@ _IO_old_file_seekoff (fp, offset, dir, mode) && !_IO_in_backup (fp)) { /* Offset relative to start of main get area. */ - _IO_pos_t rel_offset = (offset - fp->_old_offset + _IO_off_t rel_offset = (offset - fp->_old_offset + (fp->_IO_read_end - fp->_IO_read_base)); if (rel_offset >= 0) { diff --git a/libio/oldiofgetpos.c b/libio/oldiofgetpos.c new file mode 100644 index 0000000000..2b4d10ad3e --- /dev/null +++ b/libio/oldiofgetpos.c @@ -0,0 +1,61 @@ +/* Copyright (C) 1993, 95, 96, 97, 98, 99 Free Software Foundation, Inc. + This file is part of the GNU IO Library. + + This library is free software; you can redistribute it and/or + modify it under the terms of the GNU General Public License as + published by the Free Software Foundation; either version 2, or (at + your option) any later version. + + This library is distributed in the hope that it will be useful, but + WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this library; see the file COPYING. If not, write to + the Free Software Foundation, 59 Temple Place - Suite 330, Boston, + MA 02111-1307, USA. + + As a special exception, if you link this library with files + compiled with a GNU compiler to produce an executable, this does + not cause the resulting executable to be covered by the GNU General + Public License. This exception does not however invalidate any + other reasons why the executable file might be covered by the GNU + General Public License. */ + +#include "libioP.h" +#include <errno.h> + +int +_IO_old_fgetpos (fp, posp) + _IO_FILE *fp; + _IO_fpos_t *posp; +{ + _IO_off_t pos; + CHECK_FILE (fp, EOF); + _IO_cleanup_region_start ((void (*) __P ((void *))) _IO_funlockfile, fp); + _IO_flockfile (fp); + pos = _IO_seekoff (fp, 0, _IO_seek_cur, 0); + if (_IO_in_backup (fp)) + pos -= fp->_IO_save_end - fp->_IO_save_base; + _IO_funlockfile (fp); + _IO_cleanup_region_end (0); + if (pos == _IO_pos_BAD) + { + /* ANSI explicitly requires setting errno to a positive value on + failure. */ +#ifdef EIO + if (errno == 0) + __set_errno (EIO); +#endif + return EOF; + } + posp->__pos = pos; + return 0; +} + +#ifdef weak_alias +symbol_version (_IO_old_fgetpos, _IO_fgetpos, GLIBC_2.0); +strong_alias (_IO_old_fgetpos, __old_fgetpos) +symbol_version (__old_fgetpos, fgetpos, GLIBC_2.0); +#endif diff --git a/libio/oldiofgetpos64.c b/libio/oldiofgetpos64.c new file mode 100644 index 0000000000..9695c6f53d --- /dev/null +++ b/libio/oldiofgetpos64.c @@ -0,0 +1,66 @@ +/* Copyright (C) 1993, 95, 96, 97, 98, 99 Free Software Foundation, Inc. + This file is part of the GNU IO Library. + + This library is free software; you can redistribute it and/or + modify it under the terms of the GNU General Public License as + published by the Free Software Foundation; either version 2, or (at + your option) any later version. + + This library is distributed in the hope that it will be useful, but + WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this library; see the file COPYING. If not, write to + the Free Software Foundation, 59 Temple Place - Suite 330, Boston, + MA 02111-1307, USA. + + As a special exception, if you link this library with files + compiled with a GNU compiler to produce an executable, this does + not cause the resulting executable to be covered by the GNU General + Public License. This exception does not however invalidate any + other reasons why the executable file might be covered by the GNU + General Public License. */ + +#include "libioP.h" +#include <errno.h> + +int +_IO_old_fgetpos64 (fp, posp) + _IO_FILE *fp; + _IO_fpos64_t *posp; +{ +#ifdef _G_LSEEK64 + _IO_off64_t pos; + CHECK_FILE (fp, EOF); + _IO_cleanup_region_start ((void (*) __P ((void *))) _IO_funlockfile, fp); + _IO_flockfile (fp); + pos = _IO_seekoff (fp, 0, _IO_seek_cur, 0); + if (_IO_in_backup (fp)) + pos -= fp->_IO_save_end - fp->_IO_save_base; + _IO_funlockfile (fp); + _IO_cleanup_region_end (0); + if (pos == _IO_pos_BAD) + { + /* ANSI explicitly requires setting errno to a positive value on + failure. */ +#ifdef EIO + if (errno == 0) + __set_errno (EIO); +#endif + return EOF; + } + posp->__pos = pos; + return 0; +#else + __set_errno (ENOSYS); + return EOF; +#endif +} + +#ifdef weak_alias +symbol_version (_IO_old_fgetpos64, _IO_fgetpos64, GLIBC_2.0); +strong_alias (_IO_old_fgetpos64, __old_fgetpos64) +symbol_version (__old_fgetpos64, fgetpos64, GLIBC_2.0); +#endif diff --git a/libio/oldiofsetpos.c b/libio/oldiofsetpos.c new file mode 100644 index 0000000000..87a78d2eea --- /dev/null +++ b/libio/oldiofsetpos.c @@ -0,0 +1,59 @@ +/* Copyright (C) 1993, 1995, 1997, 1998, 1999 Free Software Foundation, Inc. + This file is part of the GNU IO Library. + + This library is free software; you can redistribute it and/or + modify it under the terms of the GNU General Public License as + published by the Free Software Foundation; either version 2, or (at + your option) any later version. + + This library is distributed in the hope that it will be useful, but + WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this library; see the file COPYING. If not, write to + the Free Software Foundation, 59 Temple Place - Suite 330, Boston, + MA 02111-1307, USA. + + As a special exception, if you link this library with files + compiled with a GNU compiler to produce an executable, this does + not cause the resulting executable to be covered by the GNU General + Public License. This exception does not however invalidate any + other reasons why the executable file might be covered by the GNU + General Public License. */ + +#include <libioP.h> +#include <errno.h> + +int +_IO_old_fsetpos (fp, posp) + _IO_FILE *fp; + const _IO_fpos_t *posp; +{ + int result; + CHECK_FILE (fp, EOF); + _IO_cleanup_region_start ((void (*) __P ((void *))) _IO_funlockfile, fp); + _IO_flockfile (fp); + if (_IO_seekpos (fp, posp->__pos, _IOS_INPUT|_IOS_OUTPUT) == _IO_pos_BAD) + { + /* ANSI explicitly requires setting errno to a positive value on + failure. */ +#ifdef EIO + if (errno == 0) + __set_errno (EIO); +#endif + result = EOF; + } + else + result = 0; + _IO_funlockfile (fp); + _IO_cleanup_region_end (0); + return result; +} + +#ifdef weak_alias +symbol_version (_IO_old_fsetpos, _IO_fsetpos, GLIBC_2.0); +strong_alias (_IO_old_fsetpos, __old_fsetpos) +symbol_version (__old_fsetpos, fsetpos, GLIBC_2.0); +#endif diff --git a/libio/oldiofsetpos64.c b/libio/oldiofsetpos64.c new file mode 100644 index 0000000000..9207dd71bd --- /dev/null +++ b/libio/oldiofsetpos64.c @@ -0,0 +1,64 @@ +/* Copyright (C) 1993, 1995, 1997, 1998, 1999 Free Software Foundation, Inc. + This file is part of the GNU IO Library. + + This library is free software; you can redistribute it and/or + modify it under the terms of the GNU General Public License as + published by the Free Software Foundation; either version 2, or (at + your option) any later version. + + This library is distributed in the hope that it will be useful, but + WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this library; see the file COPYING. If not, write to + the Free Software Foundation, 59 Temple Place - Suite 330, Boston, + MA 02111-1307, USA. + + As a special exception, if you link this library with files + compiled with a GNU compiler to produce an executable, this does + not cause the resulting executable to be covered by the GNU General + Public License. This exception does not however invalidate any + other reasons why the executable file might be covered by the GNU + General Public License. */ + +#include <libioP.h> +#include <errno.h> + +int +_IO_old_fsetpos64 (fp, posp) + _IO_FILE *fp; + const _IO_fpos64_t *posp; +{ +#ifdef _G_LSEEK64 + int result; + CHECK_FILE (fp, EOF); + _IO_cleanup_region_start ((void (*) __P ((void *))) _IO_funlockfile, fp); + _IO_flockfile (fp); + if (_IO_seekpos (fp, posp->__pos, _IOS_INPUT|_IOS_OUTPUT) == _IO_pos_BAD) + { + /* ANSI explicitly requires setting errno to a positive value on + failure. */ +#ifdef EIO + if (errno == 0) + __set_errno (EIO); +#endif + result = EOF; + } + else + result = 0; + _IO_funlockfile (fp); + _IO_cleanup_region_end (0); + return result; +#else + __set_errno (ENOSYS); + return EOF; +#endif +} + +#ifdef weak_alias +symbol_version (_IO_old_fsetpos64, _IO_fsetpos64, GLIBC_2.0); +strong_alias (_IO_fsetpos64, __old_fsetpos64) +symbol_version (__old_fsetpos64, _IO_fsetpos64, GLIBC_2.0); +#endif diff --git a/libio/oldstdfiles.c b/libio/oldstdfiles.c index 7781a17449..3629ab8123 100644 --- a/libio/oldstdfiles.c +++ b/libio/oldstdfiles.c @@ -1,4 +1,4 @@ -/* Copyright (C) 1993, 1994, 1996, 1997 Free Software Foundation, Inc. +/* Copyright (C) 1993, 1994, 1996, 1997, 1999 Free Software Foundation, Inc. This file is part of the GNU IO Library. This library is free software; you can redistribute it and/or @@ -37,11 +37,12 @@ #define DEF_STDFILE(NAME, FD, CHAIN, FLAGS) \ static _IO_lock_t _IO_stdfile_##FD##_lock = _IO_lock_initializer; \ struct _IO_FILE_plus NAME \ - = {FILEBUF_LITERAL(CHAIN, FLAGS, FD), &_IO_old_file_jumps}; + = {FILEBUF_LITERAL(CHAIN, FLAGS, FD, NULL), &_IO_old_file_jumps}; #else #define DEF_STDFILE(NAME, FD, CHAIN, FLAGS) \ + static struct _IO_wide_data _IO_wide_data_##FD; \ struct _IO_FILE_plus NAME \ - = {FILEBUF_LITERAL(CHAIN, FLAGS, FD), &_IO_old_file_jumps}; + = {FILEBUF_LITERAL(CHAIN, FLAGS, FD, NULL), &_IO_old_file_jumps}; #endif DEF_STDFILE(_IO_stdin_, 0, 0, _IO_NO_WRITES); diff --git a/libio/putwc.c b/libio/putwc.c new file mode 100644 index 0000000000..07557ac8c4 --- /dev/null +++ b/libio/putwc.c @@ -0,0 +1,35 @@ +/* Copyright (C) 1991, 95, 96, 97, 98, 99 Free Software Foundation, Inc. + This file is part of the GNU C Library. + + The GNU C Library is free software; you can redistribute it and/or + modify it under the terms of the GNU Library General Public License as + published by the Free Software Foundation; either version 2 of the + License, or (at your option) any later version. + + The GNU C Library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Library General Public License for more details. + + You should have received a copy of the GNU Library General Public + License along with the GNU C Library; see the file COPYING.LIB. If not, + write to the Free Software Foundation, Inc., 59 Temple Place - Suite 330, + Boston, MA 02111-1307, USA. */ + +#include "libioP.h" +#include <wchar.h> + +wint_t +putwc (wc, fp) + wint_t wc; + _IO_FILE *fp; +{ + wint_t result; + CHECK_FILE (fp, WEOF); + _IO_cleanup_region_start ((void (*) __P ((void *))) _IO_funlockfile, fp); + _IO_flockfile (fp); + result = _IO_putwc_unlocked (wc, fp); + _IO_funlockfile (fp); + _IO_cleanup_region_end (0); + return result; +} diff --git a/libio/putwc_u.c b/libio/putwc_u.c new file mode 100644 index 0000000000..3f7a26fad2 --- /dev/null +++ b/libio/putwc_u.c @@ -0,0 +1,29 @@ +/* Copyright (C) 1991, 1995, 1996, 1997, 1999 Free Software Foundation, Inc. + This file is part of the GNU C Library. + + The GNU C Library is free software; you can redistribute it and/or + modify it under the terms of the GNU Library General Public License as + published by the Free Software Foundation; either version 2 of the + License, or (at your option) any later version. + + The GNU C Library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Library General Public License for more details. + + You should have received a copy of the GNU Library General Public + License along with the GNU C Library; see the file COPYING.LIB. If not, + write to the Free Software Foundation, Inc., 59 Temple Place - Suite 330, + Boston, MA 02111-1307, USA. */ + +#include "libioP.h" +#include <wchar.h> + +wint_t +putwc_unlocked (wc, fp) + wint_t wc; + _IO_FILE *fp; +{ + CHECK_FILE (fp, WEOF); + return _IO_putc_unlocked (wc, fp); +} diff --git a/libio/putwchar.c b/libio/putwchar.c new file mode 100644 index 0000000000..0a2854f16d --- /dev/null +++ b/libio/putwchar.c @@ -0,0 +1,34 @@ +/* Copyright (C) 1991, 95, 96, 97, 98, 99 Free Software Foundation, Inc. + This file is part of the GNU C Library. + + The GNU C Library is free software; you can redistribute it and/or + modify it under the terms of the GNU Library General Public License as + published by the Free Software Foundation; either version 2 of the + License, or (at your option) any later version. + + The GNU C Library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Library General Public License for more details. + + You should have received a copy of the GNU Library General Public + License along with the GNU C Library; see the file COPYING.LIB. If not, + write to the Free Software Foundation, Inc., 59 Temple Place - Suite 330, + Boston, MA 02111-1307, USA. */ + +#include "libioP.h" +#include "stdio.h" + +wint_t +putwchar (wc) + wint_t wc; +{ + wint_t result; + _IO_cleanup_region_start ((void (*) __P ((void *))) _IO_funlockfile, + _IO_stdout); + _IO_flockfile (_IO_stdout); + result = _IO_putwc_unlocked (wc, _IO_stdout); + _IO_funlockfile (_IO_stdout); + _IO_cleanup_region_end (0); + return result; +} diff --git a/libio/putwchar_u.c b/libio/putwchar_u.c new file mode 100644 index 0000000000..0da7dcfa30 --- /dev/null +++ b/libio/putwchar_u.c @@ -0,0 +1,28 @@ +/* Copyright (C) 1991, 1995, 1996, 1997, 1999 Free Software Foundation, Inc. + This file is part of the GNU C Library. + + The GNU C Library is free software; you can redistribute it and/or + modify it under the terms of the GNU Library General Public License as + published by the Free Software Foundation; either version 2 of the + License, or (at your option) any later version. + + The GNU C Library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Library General Public License for more details. + + You should have received a copy of the GNU Library General Public + License along with the GNU C Library; see the file COPYING.LIB. If not, + write to the Free Software Foundation, Inc., 59 Temple Place - Suite 330, + Boston, MA 02111-1307, USA. */ + +#include "libioP.h" +#include "stdio.h" + +wint_t +putwchar_unlocked (c) + wint_t c; +{ + CHECK_FILE (stdout, WEOF); + return _IO_putwc_unlocked (wc, stdout); +} diff --git a/libio/stdfiles.c b/libio/stdfiles.c index 8c09c2c441..6feff4d392 100644 --- a/libio/stdfiles.c +++ b/libio/stdfiles.c @@ -1,4 +1,4 @@ -/* Copyright (C) 1993, 1994, 1996, 1997 Free Software Foundation, Inc. +/* Copyright (C) 1993, 1994, 1996, 1997, 1999 Free Software Foundation, Inc. This file is part of the GNU IO Library. This library is free software; you can redistribute it and/or @@ -35,12 +35,18 @@ #ifdef _IO_MTSAFE_IO #define DEF_STDFILE(NAME, FD, CHAIN, FLAGS) \ static _IO_lock_t _IO_stdfile_##FD##_lock = _IO_lock_initializer; \ + static struct _IO_wide_data _IO_wide_data_##FD \ + = { ._wide_vtable = &_IO_wfile_jumps }; \ struct _IO_FILE_plus NAME \ - = {FILEBUF_LITERAL(CHAIN, FLAGS, FD), &_IO_file_jumps}; + = {FILEBUF_LITERAL(CHAIN, FLAGS, FD, &_IO_wide_data_##FD), \ + &_IO_file_jumps}; #else #define DEF_STDFILE(NAME, FD, CHAIN, FLAGS) \ + static struct _IO_wide_data _IO_wide_data_##FD \ + = { ._wide_vtable = &_IO_wfile_jumps }; \ struct _IO_FILE_plus NAME \ - = {FILEBUF_LITERAL(CHAIN, FLAGS, FD), &_IO_file_jumps}; + = {FILEBUF_LITERAL(CHAIN, FLAGS, FD, &_IO_wide_data_##FD), \ + &_IO_file_jumps}; #endif DEF_STDFILE(_IO_2_1_stdin_, 0, 0, _IO_NO_WRITES); diff --git a/libio/strops.c b/libio/strops.c index c3e245f605..83fd794251 100644 --- a/libio/strops.c +++ b/libio/strops.c @@ -1,4 +1,4 @@ -/* Copyright (C) 1993, 1997, 1998 Free Software Foundation, Inc. +/* Copyright (C) 1993, 1997, 1998, 1999 Free Software Foundation, Inc. This file is part of the GNU IO Library. This library is free software; you can redistribute it and/or @@ -147,10 +147,10 @@ _IO_str_overflow (fp, c) /* __ferror(fp) = 1; */ return EOF; } - if (fp->_IO_buf_base) + if (old_buf) { memcpy (new_buf, old_buf, _IO_blen (fp)); - (*((_IO_strfile *) fp)->_s._free_buffer) (fp->_IO_buf_base); + (*((_IO_strfile *) fp)->_s._free_buffer) (old_buf); /* Make sure _IO_setb won't try to delete _IO_buf_base. */ fp->_IO_buf_base = NULL; } @@ -205,14 +205,14 @@ _IO_str_count (fp) - fp->_IO_read_base); } -_IO_fpos64_t +_IO_off64_t _IO_str_seekoff (fp, offset, dir, mode) _IO_FILE *fp; _IO_off64_t offset; int dir; int mode; { - _IO_fpos64_t new_pos; + _IO_off64_t new_pos; if (mode == 0 && (fp->_flags & _IO_TIED_PUT_GET)) mode = (fp->_flags & _IO_CURRENTLY_PUTTING ? _IOS_OUTPUT : _IOS_INPUT); diff --git a/libio/swprintf.c b/libio/swprintf.c new file mode 100644 index 0000000000..f0cb637b27 --- /dev/null +++ b/libio/swprintf.c @@ -0,0 +1,38 @@ +/* Copyright (C) 1991, 1995, 1997, 1998, 1999 Free Software Foundation, Inc. + This file is part of the GNU C Library. + + The GNU C Library is free software; you can redistribute it and/or + modify it under the terms of the GNU Library General Public License as + published by the Free Software Foundation; either version 2 of the + License, or (at your option) any later version. + + The GNU C Library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Library General Public License for more details. + + You should have received a copy of the GNU Library General Public + License along with the GNU C Library; see the file COPYING.LIB. If not, + write to the Free Software Foundation, Inc., 59 Temple Place - Suite 330, + Boston, MA 02111-1307, USA. */ + +#include <stdarg.h> +#include <wchar.h> + +/* Write formatted output into S, according to the format string FORMAT. */ +/* VARARGS3 */ +int +swprintf (s, n, format) + wchar_t *s; + size_t n; + const wchar_t *format; +{ + va_list arg; + int done; + + va_start (arg, format); + done = vswprintf (s, n, format, arg); + va_end (arg); + + return done; +} diff --git a/libio/swscanf.c b/libio/swscanf.c new file mode 100644 index 0000000000..6876d4b793 --- /dev/null +++ b/libio/swscanf.c @@ -0,0 +1,37 @@ +/* Copyright (C) 1991, 1995, 1996, 1998, 1999 Free Software Foundation, Inc. + This file is part of the GNU C Library. + + The GNU C Library is free software; you can redistribute it and/or + modify it under the terms of the GNU Library General Public License as + published by the Free Software Foundation; either version 2 of the + License, or (at your option) any later version. + + The GNU C Library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Library General Public License for more details. + + You should have received a copy of the GNU Library General Public + License along with the GNU C Library; see the file COPYING.LIB. If not, + write to the Free Software Foundation, Inc., 59 Temple Place - Suite 330, + Boston, MA 02111-1307, USA. */ + +#include <stdarg.h> +#include <wchar.h> + +/* Read formatted input from S, according to the format string FORMAT. */ +/* VARARGS2 */ +int +swscanf (s, format) + const wchar_t *s; + const wchar_t *format; +{ + va_list arg; + int done; + + va_start (arg, format); + done = vswscanf (s, format, arg); + va_end (arg); + + return done; +} diff --git a/libio/tst_swprintf.c b/libio/tst_swprintf.c new file mode 100644 index 0000000000..67d10a006d --- /dev/null +++ b/libio/tst_swprintf.c @@ -0,0 +1,42 @@ +#include <stdio.h> +#include <wchar.h> + +int +main (int argc, char *argv[]) +{ + wchar_t buf[100]; + int n; + int result = 0; + + puts ("test 1"); + n = swprintf (buf, sizeof (buf) / sizeof (buf[0]), L"Hello %s", "world"); + if (n != 11) + { + printf ("incorrect return value: %d instead of 11\n", n); + result = 1; + } + + if (wcscmp (buf, L"Hello world") != 0) + { + printf ("incorrect string: L\"%ls\" instead of L\"Hello world\"\n", buf); + result = 1; + } + + puts ("test 2"); + n = swprintf (buf, sizeof (buf) / sizeof (buf[0]), L"Is this >%g< 3.1?", + 3.1); + if (n != 18) +{ + printf ("incorrect return value: %d instead of 18\n", n); + result = 1; + } + + if (wcscmp (buf, L"Is this >3.1< 3.1?") != 0) + { + printf ("incorrect string: L\"%ls\" instead of L\"Is this >3.1< 3.1?\"\n", + buf); + result = 1; + } + + return result; +} diff --git a/libio/tst_swscanf.c b/libio/tst_swscanf.c new file mode 100644 index 0000000000..ce56144bb0 --- /dev/null +++ b/libio/tst_swscanf.c @@ -0,0 +1,38 @@ +#include <stdio.h> +#include <wchar.h> + +int +main (int argc, char *argv[]) +{ + const wchar_t in[] = L"7 + 35 is 42"; + size_t n; + int a, b, c; + int result = 0; + char buf1[20]; + wchar_t wbuf2[20]; + char buf3[20]; + char c4; + wchar_t wc5; + + puts ("Test 1"); + a = b = c = 0; + n = swscanf (in, L"%d + %d is %d", &a, &b, &c); + if (n != 3 || a + b != c || c != 42) + { + printf ("*** FAILED, n = %Zu, a = %d, b = %d, c = %d\n", n, a, b, c); + result = 1; + } + + puts ("Test 2"); + n = swscanf (L"one two three !!", L"%s %S %s %c%C", + buf1, wbuf2, buf3, &c4, &wc5); + if (n != 5 || strcmp (buf1, "one") != 0 || wcscmp (wbuf2, L"two") != 0 + || strcmp (buf3, "three") != 0 || c4 != '!' || wc5 != L'!') + { + printf ("*** FAILED, n = %Zu, buf1 = \"%s\", wbuf2 = L\"%S\", buf3 = \"%s\", c4 = '%c', wc5 = L'%C'\n", + n, buf1, wbuf2, buf3, c4, wc5); + result = 1; + } + + return result; +} diff --git a/libio/tst_wprintf.c b/libio/tst_wprintf.c new file mode 100644 index 0000000000..0838441d2c --- /dev/null +++ b/libio/tst_wprintf.c @@ -0,0 +1,10 @@ +#include <stdio.h> +#include <wchar.h> + +int +main (int argc, char *argv[]) +{ + fputws (L"Hello world!\n", stdout); + wprintf (L"This %s a %ls string: %d\n", "is", L"mixed", 42); + return 0; +} diff --git a/libio/tst_wscanf.c b/libio/tst_wscanf.c new file mode 100644 index 0000000000..719f37867e --- /dev/null +++ b/libio/tst_wscanf.c @@ -0,0 +1,28 @@ +#include <stdio.h> +#include <wchar.h> + +int +main (int argc, char *argv[]) +{ + int n; + int result = 0; + char buf1[20]; + wchar_t wbuf2[20]; + char c3; + wchar_t wc4; + int d; + + puts ("Test 1"); + + n = wscanf (L"%s %S %c%C %d", buf1, wbuf2, &c3, &wc4, &d); + + if (n != 5 || strcmp (buf1, "Hello") != 0 || wcscmp (wbuf2, L"World") != 0 + || c3 != '!' || wc4 != L'!' || d != 42) + { + printf ("*** FAILED, n = %d, buf1 = \"%s\", wbuf2 = L\"%S\", c3 = '%c', wc4 = L'%C', d = %d\n", + n, buf1, wbuf2, c3, wc4, d); + result = 1; + } + + return result; +} diff --git a/libio/tst_wscanf.input b/libio/tst_wscanf.input new file mode 100644 index 0000000000..93e1eb55d4 --- /dev/null +++ b/libio/tst_wscanf.input @@ -0,0 +1 @@ +Hello World !! 42 diff --git a/libio/vasprintf.c b/libio/vasprintf.c index 15513d0fca..a656961167 100644 --- a/libio/vasprintf.c +++ b/libio/vasprintf.c @@ -1,4 +1,4 @@ -/* Copyright (C) 1995, 1997 Free Software Foundation, Inc. +/* Copyright (C) 1995, 1997, 1999 Free Software Foundation, Inc. This file is part of the GNU IO Library. This library is free software; you can redistribute it and/or @@ -49,7 +49,7 @@ _IO_vasprintf (result_ptr, format, args) #ifdef _IO_MTSAFE_IO sf._sbf._f._lock = &lock; #endif - _IO_init ((_IO_FILE *) &sf, 0); + _IO_no_init ((_IO_FILE *) &sf, 0, -1, NULL, NULL); _IO_JUMPS ((_IO_FILE *) &sf) = &_IO_str_jumps; _IO_str_init_static ((_IO_FILE *) &sf, string, init_string_size, string); sf._sbf._f._flags &= ~_IO_USER_BUF; diff --git a/libio/vsnprintf.c b/libio/vsnprintf.c index e223e5dec2..2b82df5788 100644 --- a/libio/vsnprintf.c +++ b/libio/vsnprintf.c @@ -1,4 +1,4 @@ -/* Copyright (C) 1994, 1997 Free Software Foundation, Inc. +/* Copyright (C) 1994, 1997, 1999 Free Software Foundation, Inc. This file is part of the GNU IO Library. This library is free software; you can redistribute it and/or @@ -122,7 +122,7 @@ _IO_vsnprintf (string, maxlen, format, args) maxlen = sizeof (sf.overflow_buf); } - _IO_init ((_IO_FILE *) &sf, 0); + _IO_no_init ((_IO_FILE *) &sf, 0, -1, NULL, NULL); _IO_JUMPS ((_IO_FILE *) &sf) = &_IO_strn_jumps; string[0] = '\0'; _IO_str_init_static ((_IO_FILE *) &sf, string, maxlen - 1, string); diff --git a/libio/vswprintf.c b/libio/vswprintf.c new file mode 100644 index 0000000000..addf39089c --- /dev/null +++ b/libio/vswprintf.c @@ -0,0 +1,144 @@ +/* Copyright (C) 1994, 1997, 1999 Free Software Foundation, Inc. + This file is part of the GNU IO Library. + + This library is free software; you can redistribute it and/or + modify it under the terms of the GNU General Public License as + published by the Free Software Foundation; either version 2, or (at + your option) any later version. + + This library is distributed in the hope that it will be useful, but + WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this library; see the file COPYING. If not, write to + the Free Software Foundation, 59 Temple Place - Suite 330, Boston, + MA 02111-1307, USA. + + As a special exception, if you link this library with files + compiled with a GNU compiler to produce an executable, this does + not cause the resulting executable to be covered by the GNU General + Public License. This exception does not however invalidate any + other reasons why the executable file might be covered by the GNU + General Public License. */ + +#include "libioP.h" +#include "strfile.h" + + +typedef struct +{ + _IO_strfile f; + /* This is used for the characters which do not fit in the buffer + provided by the user. */ + wchar_t overflow_buf[64]; +} _IO_strnfile; + + +static wint_t _IO_wstrn_overflow __P ((_IO_FILE *fp, wint_t c)); + +static wint_t +_IO_wstrn_overflow (fp, c) + _IO_FILE *fp; + wint_t c; +{ + /* When we come to here this means the user supplied buffer is + filled. But since we must return the number of characters which + would have been written in total we must provide a buffer for + further use. We can do this by writing on and on in the overflow + buffer in the _IO_strnfile structure. */ + _IO_strnfile *snf = (_IO_strnfile *) fp; + + if (fp->_wide_data->_IO_buf_base != snf->overflow_buf) + { + /* Terminate the string. We know that there is room for at + least one more character since we initialized the stream with + a size to make this possible. */ + *fp->_wide_data->_IO_write_ptr = '\0'; + + _IO_wsetb (fp, snf->overflow_buf, + snf->overflow_buf + (sizeof (snf->overflow_buf) + / sizeof (wchar_t)), 0); + + fp->_wide_data->_IO_write_base = snf->overflow_buf; + fp->_wide_data->_IO_read_base = snf->overflow_buf; + fp->_wide_data->_IO_read_ptr = snf->overflow_buf; + fp->_wide_data->_IO_read_end = (snf->overflow_buf + + (sizeof (snf->overflow_buf) + / sizeof (wchar_t))); + } + + fp->_wide_data->_IO_write_ptr = snf->overflow_buf; + fp->_wide_data->_IO_write_end = snf->overflow_buf; + + /* Since we are not really interested in storing the characters + which do not fit in the buffer we simply ignore it. */ + return c; +} + + +static struct _IO_jump_t _IO_wstrn_jumps = +{ + JUMP_INIT_DUMMY, + JUMP_INIT(finish, _IO_wstr_finish), + JUMP_INIT(overflow, (_IO_overflow_t) _IO_wstrn_overflow), + JUMP_INIT(underflow, (_IO_underflow_t) _IO_wstr_underflow), + JUMP_INIT(uflow, (_IO_underflow_t) _IO_wdefault_uflow), + JUMP_INIT(pbackfail, (_IO_pbackfail_t) _IO_wstr_pbackfail), + JUMP_INIT(xsputn, _IO_wdefault_xsputn), + JUMP_INIT(xsgetn, _IO_wdefault_xsgetn), + JUMP_INIT(seekoff, _IO_wstr_seekoff), + JUMP_INIT(seekpos, _IO_default_seekpos), + JUMP_INIT(setbuf, (_IO_setbuf_t) _IO_wdefault_setbuf), + JUMP_INIT(sync, _IO_default_sync), + JUMP_INIT(doallocate, _IO_wdefault_doallocate), + JUMP_INIT(read, _IO_default_read), + JUMP_INIT(write, _IO_default_write), + JUMP_INIT(seek, _IO_default_seek), + JUMP_INIT(close, _IO_default_close), + JUMP_INIT(stat, _IO_default_stat), + JUMP_INIT(showmanyc, _IO_default_showmanyc), + JUMP_INIT(imbue, _IO_default_imbue) +}; + + +int +_IO_vswprintf (string, maxlen, format, args) + wchar_t *string; + _IO_size_t maxlen; + const wchar_t *format; + _IO_va_list args; +{ + _IO_strnfile sf; + int ret; + struct _IO_wide_data wd; +#ifdef _IO_MTSAFE_IO + _IO_lock_t lock; + sf.f._sbf._f._lock = &lock; +#endif + + /* We need to handle the special case where MAXLEN is 0. Use the + overflow buffer right from the start. */ + if (maxlen == 0) + { + string = sf.overflow_buf; + maxlen = sizeof (sf.overflow_buf) / sizeof (wchar_t); + } + + _IO_no_init ((_IO_FILE *) &sf, 0, 0, &wd, NULL); + _IO_WIDE_JUMPS ((_IO_FILE *) &sf) = &_IO_wstrn_jumps; + _IO_fwide (&sf.f._sbf._f, 1); + string[0] = L'\0'; + _IO_wstr_init_static ((_IO_FILE *) &sf, string, maxlen - 1, string); + ret = _IO_vfwprintf ((_IO_FILE *) &sf, format, args); + + if (sf.f._sbf._f._wide_data->_IO_buf_base != sf.overflow_buf) + *sf.f._sbf._f._wide_data->_IO_write_ptr = '\0'; + return ret; +} + +#ifdef weak_alias +weak_alias (_IO_vswprintf, __vswprintf) +weak_alias (_IO_vswprintf, vswprintf) +#endif diff --git a/libio/vwprintf.c b/libio/vwprintf.c new file mode 100644 index 0000000000..1f3102e4ff --- /dev/null +++ b/libio/vwprintf.c @@ -0,0 +1,31 @@ +/* Copyright (C) 1991, 1993, 1995, 1997, 1999 Free Software Foundation, Inc. + This file is part of the GNU C Library. + + The GNU C Library is free software; you can redistribute it and/or + modify it under the terms of the GNU Library General Public License as + published by the Free Software Foundation; either version 2 of the + License, or (at your option) any later version. + + The GNU C Library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Library General Public License for more details. + + You should have received a copy of the GNU Library General Public + License along with the GNU C Library; see the file COPYING.LIB. If not, + write to the Free Software Foundation, Inc., 59 Temple Place - Suite 330, + Boston, MA 02111-1307, USA. */ + +#include <stdarg.h> +#undef __OPTIMIZE__ /* Avoid inline `vwprintf' function. */ +#include <stdio.h> + +/* Write formatted output to stdout according to the + format string FORMAT, using the argument list in ARG. */ +int +vwprintf (format, arg) + const wchar_t *format; + __gnuc_va_list arg; +{ + return vfwprintf (stdout, format, arg); +} diff --git a/libio/vwscanf.c b/libio/vwscanf.c new file mode 100644 index 0000000000..fb24fc9baa --- /dev/null +++ b/libio/vwscanf.c @@ -0,0 +1,35 @@ +/* Copyright (C) 1993, 1997, 1999 Free Software Foundation, Inc. + This file is part of the GNU IO Library. + + This library is free software; you can redistribute it and/or + modify it under the terms of the GNU General Public License as + published by the Free Software Foundation; either version 2, or (at + your option) any later version. + + This library is distributed in the hope that it will be useful, but + WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this library; see the file COPYING. If not, write to + the Free Software Foundation, 59 Temple Place - Suite 330, Boston, + MA 02111-1307, USA. + + As a special exception, if you link this library with files + compiled with a GNU compiler to produce an executable, this does + not cause the resulting executable to be covered by the GNU General + Public License. This exception does not however invalidate any + other reasons why the executable file might be covered by the GNU + General Public License. */ + +#include "libioP.h" +#include <wchar.h> + +int +vwscanf (format, args) + const wchar_t *format; + _IO_va_list args; +{ + return _IO_vfwscanf (_IO_stdin, format, args, NULL); +} diff --git a/libio/wfiledoalloc.c b/libio/wfiledoalloc.c new file mode 100644 index 0000000000..7f5cb7f960 --- /dev/null +++ b/libio/wfiledoalloc.c @@ -0,0 +1,105 @@ +/* Copyright (C) 1993, 1997, 1999 Free Software Foundation, Inc. + This file is part of the GNU IO Library. + + This library is free software; you can redistribute it and/or + modify it under the terms of the GNU General Public License as + published by the Free Software Foundation; either version 2, or (at + your option) any later version. + + This library is distributed in the hope that it will be useful, but + WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this library; see the file COPYING. If not, write to + the Free Software Foundation, 59 Temple Place - Suite 330, Boston, + MA 02111-1307, USA. + + As a special exception, if you link this library with files + compiled with a GNU compiler to produce an executable, this does + not cause the resulting executable to be covered by the GNU General + Public License. This exception does not however invalidate any + other reasons why the executable file might be covered by the GNU + General Public License. */ + +/* + * Copyright (c) 1990 The Regents of the University of California. + * All rights reserved. + * + * Redistribution and use in source and binary forms are permitted + * provided that the above copyright notice and this paragraph are + * duplicated in all such forms and that any documentation, + * advertising materials, and other materials related to such + * distribution and use acknowledge that the software was developed + * by the University of California, Berkeley. The name of the + * University may not be used to endorse or promote products derived + * from this software without specific prior written permission. + * THIS SOFTWARE IS PROVIDED ``AS IS'' AND WITHOUT ANY EXPRESS OR + * IMPLIED WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED + * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE. + */ + +/* Modified for GNU iostream by Per Bothner 1991, 1992. */ + +#ifndef _POSIX_SOURCE +# define _POSIX_SOURCE +#endif +#include "libioP.h" +#include <sys/types.h> +#include <sys/stat.h> +#ifdef __STDC__ +#include <stdlib.h> +#include <unistd.h> +#endif + +#ifdef _LIBC +# undef isatty +# define isatty(Fd) __isatty (Fd) +#endif + +/* + * Allocate a file buffer, or switch to unbuffered I/O. + * Per the ANSI C standard, ALL tty devices default to line buffered. + * + * As a side effect, we set __SOPT or __SNPT (en/dis-able fseek + * optimisation) right after the _fstat() that finds the buffer size. + */ + +int +_IO_wfile_doallocate (fp) + _IO_FILE *fp; +{ + _IO_size_t size; + int couldbetty; + wchar_t *p; + struct _G_stat64 st; + + /* Allocate room for the external buffer. */ + _IO_file_doallocate (fp); + + if (fp->_fileno < 0 || _IO_SYSSTAT (fp, &st) < 0) + { + couldbetty = 0; + size = _IO_BUFSIZ * sizeof (wchar_t); +#if 0 + /* do not try to optimise fseek() */ + fp->_flags |= __SNPT; +#endif + } + else + { + couldbetty = S_ISCHR (st.st_mode); +#if _IO_HAVE_ST_BLKSIZE + size = ((st.st_blksize <= 0 ? _IO_BUFSIZ : st.st_blksize) + * sizeof (wchar_t)); +#else + size = _IO_BUFSIZ * sizeof (wchar_t); +#endif + } + ALLOC_WBUF (p, size, EOF); + _IO_wsetb (fp, p, p + size, 1); + if (couldbetty && isatty (fp->_fileno)) + fp->_flags |= _IO_LINE_BUF; + return 1; +} diff --git a/libio/wfileops.c b/libio/wfileops.c new file mode 100644 index 0000000000..b040b97491 --- /dev/null +++ b/libio/wfileops.c @@ -0,0 +1,716 @@ +/* Copyright (C) 1993, 1995, 1997, 1998, 1999 Free Software Foundation, Inc. + This file is part of the GNU IO Library. + Written by Ulrich Drepper <drepper@cygnus.com>. + Based on the single byte version by Per Bothner <bothner@cygnus.com>. + + This library is free software; you can redistribute it and/or + modify it under the terms of the GNU General Public License as + published by the Free Software Foundation; either version 2, or (at + your option) any later version. + + This library is distributed in the hope that it will be useful, but + WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this library; see the file COPYING. If not, write to + the Free Software Foundation, 59 Temple Place - Suite 330, Boston, + MA 02111-1307, USA. + + As a special exception, if you link this library with files + compiled with a GNU compiler to produce an executable, this does + not cause the resulting executable to be covered by the GNU General + Public License. This exception does not however invalidate any + other reasons why the executable file might be covered by the GNU + General Public License. */ + +#include <assert.h> +#include <libioP.h> +#include <wchar.h> +#include <gconv.h> +#include <stdlib.h> +#include <string.h> + + +_IO_FILE * +_IO_wfile_setbuf (fp, p, len) + _IO_FILE *fp; + wchar_t *p; + _IO_ssize_t len; +{ + if (_IO_wdefault_setbuf (fp, p, len) == NULL) + return NULL; + + fp->_wide_data->_IO_write_base = fp->_wide_data->_IO_write_ptr = + fp->_wide_data->_IO_write_end = fp->_wide_data->_IO_buf_base; + _IO_wsetg (fp, fp->_wide_data->_IO_buf_base, fp->_wide_data->_IO_buf_base, + fp->_wide_data->_IO_buf_base); + + return fp; +} + + +/* Convert TO_DO wide character from DATA to FP. + Then mark FP as having empty buffers. */ +int +_IO_wdo_write (fp, data, to_do) + _IO_FILE *fp; + const wchar_t *data; + _IO_size_t to_do; +{ + struct _IO_codecvt *cc = &fp->_wide_data->_codecvt; + _IO_size_t count = 0; + + while (to_do > 0) + { + enum __codecvt_result result; + const wchar_t *new_data; + + if (fp->_IO_write_end == fp->_IO_write_ptr) + { + _IO_new_file_overflow (fp, EOF); + assert (fp->_IO_write_end > fp->_IO_write_ptr); + } + + /* Now convert from the internal format into the external buffer. */ + result = (*cc->__codecvt_do_out) (cc, &fp->_wide_data->_IO_state, + data, data + to_do, &new_data, + fp->_IO_write_ptr, + fp->_IO_write_end, + &fp->_IO_write_ptr); + + /* Write out what we produced so far. */ + if (_IO_new_do_write (fp, fp->_IO_write_base, + fp->_IO_write_ptr - fp->_IO_write_base) == EOF) + /* Something went wrong. */ + return EOF; + + count += new_data - data; + to_do -= new_data - data; + data = new_data; + + /* Next see whether we had problems during the conversion. If yes, + we cannot go on. */ + if (result != __codecvt_ok) + break; + } + + _IO_wsetg (fp, fp->_wide_data->_IO_buf_base, fp->_wide_data->_IO_buf_base, + fp->_wide_data->_IO_buf_base); + fp->_wide_data->_IO_write_base = fp->_wide_data->_IO_write_ptr + = fp->_wide_data->_IO_buf_base; + fp->_wide_data->_IO_write_end = ((fp->_flags & (_IO_LINE_BUF+_IO_UNBUFFERED)) + ? fp->_wide_data->_IO_buf_base + : fp->_wide_data->_IO_buf_end); + + return count; +} + + +wint_t +_IO_wfile_underflow (fp) + _IO_FILE *fp; +{ + struct _IO_codecvt *cd; + enum __codecvt_result status; + _IO_ssize_t count; + int tries; + const char *read_ptr_copy; + + if (fp->_flags & _IO_NO_READS) + { + __set_errno (EBADF); + return WEOF; + } + if (fp->_wide_data->_IO_read_ptr < fp->_wide_data->_IO_read_end) + return *fp->_wide_data->_IO_read_ptr; + + cd = &fp->_wide_data->_codecvt; + + /* Maybe there is something left in the external buffer. */ + if (fp->_IO_read_ptr < fp->_IO_read_end) + { + /* Convert it. */ + size_t avail_bytes = fp->_IO_read_end - fp->_IO_read_ptr; + + if (avail_bytes >= (*cd->__codecvt_do_max_length) (cd)) + { + /* There is more in the external. */ + const char *read_stop = (const char *) fp->_IO_read_ptr; + + fp->_wide_data->_IO_last_state = fp->_wide_data->_IO_state; + status = (*cd->__codecvt_do_in) (cd, &fp->_wide_data->_IO_state, + fp->_IO_read_ptr, fp->_IO_read_end, + &read_stop, + fp->_wide_data->_IO_read_end, + fp->_wide_data->_IO_buf_end, + &fp->_wide_data->_IO_read_end); + + fp->_IO_read_ptr = (char *) read_stop; + + /* If we managed to generate some text return the next character. */ + if (fp->_wide_data->_IO_read_ptr < fp->_wide_data->_IO_read_end) + return *fp->_wide_data->_IO_read_ptr; + + if (status == __codecvt_error) + { + __set_errno (EILSEQ); + fp->_flags |= _IO_ERR_SEEN; + return WEOF; + } + } + + /* Move the remaining content of the read buffer to the beginning. */ + memmove (fp->_IO_buf_base, fp->_IO_read_ptr, + fp->_IO_read_end - fp->_IO_read_ptr); + fp->_IO_read_end = (fp->_IO_buf_base + + (fp->_IO_read_end - fp->_IO_read_ptr)); + fp->_IO_read_base = fp->_IO_read_ptr = fp->_IO_buf_base; + } + else + fp->_IO_read_base = fp->_IO_read_ptr = fp->_IO_read_end = + fp->_IO_buf_base; + + fp->_IO_write_base = fp->_IO_write_ptr = fp->_IO_write_end = + fp->_IO_buf_base; + + if (fp->_IO_buf_base == NULL) + { + /* Maybe we already have a push back pointer. */ + if (fp->_IO_save_base != NULL) + { + free (fp->_IO_save_base); + fp->_flags &= ~_IO_IN_BACKUP; + } + _IO_doallocbuf (fp); + } + + if (fp->_wide_data->_IO_buf_base == NULL) + { + /* Maybe we already have a push back pointer. */ + if (fp->_wide_data->_IO_save_base != NULL) + { + free (fp->_wide_data->_IO_save_base); + fp->_flags &= ~_IO_IN_BACKUP; + } + _IO_wdoallocbuf (fp); + } + + /* Flush all line buffered files before reading. */ + /* FIXME This can/should be moved to genops ?? */ + if (fp->_flags & (_IO_LINE_BUF|_IO_UNBUFFERED)) + _IO_flush_all_linebuffered (); + + _IO_switch_to_get_mode (fp); + + fp->_IO_read_base = fp->_IO_read_ptr = fp->_IO_buf_base; + fp->_IO_read_end = fp->_IO_buf_base; + fp->_IO_write_base = fp->_IO_write_ptr = fp->_IO_write_end + = fp->_IO_buf_base; + + fp->_wide_data->_IO_read_base = fp->_wide_data->_IO_read_ptr = + fp->_wide_data->_IO_buf_base; + fp->_wide_data->_IO_read_end = fp->_wide_data->_IO_buf_base; + fp->_wide_data->_IO_write_base = fp->_wide_data->_IO_write_ptr = + fp->_wide_data->_IO_write_end = fp->_wide_data->_IO_buf_base; + + tries = 0; + again: + count = _IO_SYSREAD (fp, fp->_IO_read_end, + fp->_IO_buf_end - fp->_IO_read_end); + if (count <= 0) + { + if (count == 0 && tries == 0) + fp->_flags |= _IO_EOF_SEEN; + else + fp->_flags |= _IO_ERR_SEEN, count = 0; + } + fp->_IO_read_end += count; + if (count == 0) + { + if (tries != 0) + /* There are some bytes in the external buffer but they don't + convert to anything. */ + __set_errno (EILSEQ); + return WEOF; + } + if (fp->_offset != _IO_pos_BAD) + _IO_pos_adjust (fp->_offset, count); + + /* Now convert the read input. */ + fp->_wide_data->_IO_last_state = fp->_wide_data->_IO_state; + fp->_IO_read_base = fp->_IO_read_ptr; + status = (*cd->__codecvt_do_in) (cd, &fp->_wide_data->_IO_state, + fp->_IO_read_ptr, fp->_IO_read_end, + &read_ptr_copy, + fp->_wide_data->_IO_read_end, + fp->_wide_data->_IO_buf_end, + &fp->_wide_data->_IO_read_end); + + fp->_IO_read_ptr = (char *) read_ptr_copy; + if (fp->_wide_data->_IO_read_end == fp->_wide_data->_IO_buf_base) + { + if (status == __codecvt_error || fp->_IO_read_end == fp->_IO_buf_end) + { + __set_errno (EILSEQ); + fp->_flags |= _IO_ERR_SEEN; + return WEOF; + } + + /* The read bytes make no complete character. Try reading again. */ + assert (status == __codecvt_partial); + ++tries; + goto again; + } + + return *fp->_wide_data->_IO_read_ptr; +} + + +wint_t +_IO_wfile_overflow (f, wch) + _IO_FILE *f; + wint_t wch; +{ + if (f->_flags & _IO_NO_WRITES) /* SET ERROR */ + { + f->_flags |= _IO_ERR_SEEN; + __set_errno (EBADF); + return WEOF; + } + /* If currently reading or no buffer allocated. */ + if ((f->_flags & _IO_CURRENTLY_PUTTING) == 0) + { + /* Allocate a buffer if needed. */ + if (f->_wide_data->_IO_write_base == 0) + { + _IO_wdoallocbuf (f); + _IO_wsetg (f, f->_wide_data->_IO_buf_base, + f->_wide_data->_IO_buf_base, f->_wide_data->_IO_buf_base); + } + else + { + /* Otherwise must be currently reading. If _IO_read_ptr + (and hence also _IO_read_end) is at the buffer end, + logically slide the buffer forwards one block (by setting + the read pointers to all point at the beginning of the + block). This makes room for subsequent output. + Otherwise, set the read pointers to _IO_read_end (leaving + that alone, so it can continue to correspond to the + external position). */ + if (f->_wide_data->_IO_read_ptr == f->_wide_data->_IO_buf_end) + { + f->_IO_read_end = f->_IO_read_ptr = f->_IO_buf_base; + f->_wide_data->_IO_read_end = f->_wide_data->_IO_read_ptr = + f->_wide_data->_IO_buf_base; + } + } + f->_wide_data->_IO_write_ptr = f->_wide_data->_IO_read_ptr; + f->_wide_data->_IO_write_base = f->_wide_data->_IO_write_ptr; + f->_wide_data->_IO_write_end = f->_wide_data->_IO_buf_end; + f->_wide_data->_IO_read_base = f->_wide_data->_IO_read_ptr = + f->_wide_data->_IO_read_end; + + f->_flags |= _IO_CURRENTLY_PUTTING; + if (f->_flags & (_IO_LINE_BUF+_IO_UNBUFFERED)) + f->_wide_data->_IO_write_end = f->_wide_data->_IO_write_ptr; + } + if (wch == WEOF) + return _IO_do_flush (f); + if (f->_wide_data->_IO_write_ptr == f->_wide_data->_IO_buf_end ) + /* Buffer is really full */ + if (_IO_do_flush (f) == WEOF) + return WEOF; + *f->_wide_data->_IO_write_ptr++ = wch; + if ((f->_flags & _IO_UNBUFFERED) + || ((f->_flags & _IO_LINE_BUF) && wch == L'\n')) + if (_IO_do_flush (f) == WEOF) + return WEOF; + return wch; +} + +wint_t +_IO_wfile_sync (fp) + _IO_FILE *fp; +{ + _IO_ssize_t delta; + wint_t retval = 0; + + /* char* ptr = cur_ptr(); */ + if (fp->_wide_data->_IO_write_ptr > fp->_wide_data->_IO_write_base) + if (_IO_do_flush (fp)) + return WEOF; + delta = fp->_wide_data->_IO_read_ptr - fp->_wide_data->_IO_read_end; + if (delta != 0) + { + /* We have to find out how many bytes we have to go back in the + external buffer. */ + struct _IO_codecvt *cv = &fp->_wide_data->_codecvt; + _IO_off64_t new_pos; + + int clen = (*cv->__codecvt_do_encoding) (cv); + + if (clen > 0) + /* It is easy, a fixed number of input bytes are used for each + wide character. */ + delta *= clen; + else + { + /* We have to find out the hard way how much to back off. + To do this we determine how much input we needed to + generate the wide characters up to the current reading + position. */ + int nread; + + fp->_wide_data->_IO_state = fp->_wide_data->_IO_last_state; + nread = (*cv->__codecvt_do_length) (cv, &fp->_wide_data->_IO_state, + fp->_IO_read_base, + fp->_IO_read_end, delta); + fp->_IO_read_ptr = fp->_IO_read_base + nread; + delta = -(fp->_IO_read_end - fp->_IO_read_base - nread); + } + + new_pos = _IO_SYSSEEK (fp, delta, 1); + if (new_pos != (_IO_off64_t) EOF) + { + fp->_wide_data->_IO_read_end = fp->_wide_data->_IO_read_ptr; + fp->_IO_read_end = fp->_IO_read_ptr; + } +#ifdef ESPIPE + else if (errno == ESPIPE) + ; /* Ignore error from unseekable devices. */ +#endif + else + retval = WEOF; + } + if (retval != WEOF) + fp->_offset = _IO_pos_BAD; + /* FIXME: Cleanup - can this be shared? */ + /* setg(base(), ptr, ptr); */ + return retval; +} + +_IO_off64_t +_IO_wfile_seekoff (fp, offset, dir, mode) + _IO_FILE *fp; + _IO_off64_t offset; + int dir; + int mode; +{ + _IO_off64_t result; + _IO_off64_t delta, new_offset; + long int count; + /* POSIX.1 8.2.3.7 says that after a call the fflush() the file + offset of the underlying file must be exact. */ + int must_be_exact = ((fp->_wide_data->_IO_read_base + == fp->_wide_data->_IO_read_end) + && (fp->_wide_data->_IO_write_base + == fp->_wide_data->_IO_write_ptr)); + + if (mode == 0) + dir = _IO_seek_cur, offset = 0; /* Don't move any pointers. */ + + /* Flush unwritten characters. + (This may do an unneeded write if we seek within the buffer. + But to be able to switch to reading, we would need to set + egptr to ptr. That can't be done in the current design, + which assumes file_ptr() is eGptr. Anyway, since we probably + end up flushing when we close(), it doesn't make much difference.) + FIXME: simulate mem-papped files. */ + + if (fp->_wide_data->_IO_write_ptr > fp->_wide_data->_IO_write_base + || _IO_in_put_mode (fp)) + if (_IO_switch_to_get_mode (fp)) + return WEOF; + + if (fp->_wide_data->_IO_buf_base == NULL) + { + /* It could be that we already have a pushback buffer. */ + if (fp->_wide_data->_IO_read_base != NULL) + { + free (fp->_wide_data->_IO_read_base); + fp->_flags &= ~_IO_IN_BACKUP; + } + _IO_doallocbuf (fp); + _IO_setp (fp, fp->_IO_buf_base, fp->_IO_buf_base); + _IO_setg (fp, fp->_IO_buf_base, fp->_IO_buf_base, fp->_IO_buf_base); + _IO_wsetp (fp, fp->_wide_data->_IO_buf_base, + fp->_wide_data->_IO_buf_base); + _IO_wsetg (fp, fp->_wide_data->_IO_buf_base, + fp->_wide_data->_IO_buf_base, fp->_wide_data->_IO_buf_base); + } + + switch (dir) + { + struct _IO_codecvt *cv; + int clen; + + case _IO_seek_cur: + /* Adjust for read-ahead (bytes is buffer). To do this we must + find out which position in the external buffer corresponds to + the current position in the internal buffer. */ + cv = &fp->_wide_data->_codecvt; + clen = (*cv->__codecvt_do_encoding) (cv); + + if (clen > 0) + offset -= (fp->_wide_data->_IO_read_end + - fp->_wide_data->_IO_read_ptr) * clen; + else + { + int nread; + + delta = fp->_wide_data->_IO_read_ptr - fp->_wide_data->_IO_read_end; + fp->_wide_data->_IO_state = fp->_wide_data->_IO_last_state; + nread = (*cv->__codecvt_do_length) (cv, &fp->_wide_data->_IO_state, + fp->_IO_read_base, + fp->_IO_read_end, delta); + fp->_IO_read_ptr = fp->_IO_read_base + nread; + offset -= fp->_IO_read_end - fp->_IO_read_base - nread; + } + + if (fp->_offset == _IO_pos_BAD) + goto dumb; + /* Make offset absolute, assuming current pointer is file_ptr(). */ + offset += fp->_offset; + + dir = _IO_seek_set; + break; + case _IO_seek_set: + break; + case _IO_seek_end: + { + struct _G_stat64 st; + if (_IO_SYSSTAT (fp, &st) == 0 && S_ISREG (st.st_mode)) + { + offset += st.st_size; + dir = _IO_seek_set; + } + else + goto dumb; + } + } + /* At this point, dir==_IO_seek_set. */ + + /* If we are only interested in the current position we've found it now. */ + if (mode == 0) + return offset; + + /* If destination is within current buffer, optimize: */ + if (fp->_offset != _IO_pos_BAD && fp->_IO_read_base != NULL + && !_IO_in_backup (fp)) + { + /* Offset relative to start of main get area. */ + _IO_off64_t rel_offset = (offset - fp->_offset + + (fp->_IO_read_end - fp->_IO_read_base)); + if (rel_offset >= 0) + { +#if 0 + if (_IO_in_backup (fp)) + _IO_switch_to_main_get_area (fp); +#endif + if (rel_offset <= fp->_IO_read_end - fp->_IO_read_base) + { + fp->_IO_read_ptr = fp->_IO_read_base + rel_offset; + _IO_setp (fp, fp->_IO_buf_base, fp->_IO_buf_base); + + /* Now set the pointer for the internal buffer. This + might be an iterative process. Though the read + pointer is somewhere in the current external buffer + this does not mean we can convert this whole buffer + at once fitting in the internal buffer. */ + do + { + + } + while (0); + + _IO_mask_flags (fp, 0, _IO_EOF_SEEN); + goto resync; + } +#ifdef TODO + /* If we have streammarkers, seek forward by reading ahead. */ + if (_IO_have_markers (fp)) + { + int to_skip = rel_offset + - (fp->_IO_read_ptr - fp->_IO_read_base); + if (ignore (to_skip) != to_skip) + goto dumb; + _IO_mask_flags (fp, 0, _IO_EOF_SEEN); + goto resync; + } +#endif + } +#ifdef TODO + if (rel_offset < 0 && rel_offset >= Bbase () - Bptr ()) + { + if (!_IO_in_backup (fp)) + _IO_switch_to_backup_area (fp); + gbump (fp->_IO_read_end + rel_offset - fp->_IO_read_ptr); + _IO_mask_flags (fp, 0, _IO_EOF_SEEN); + goto resync; + } +#endif + } + +#ifdef TODO + _IO_unsave_markers (fp); +#endif + + if (fp->_flags & _IO_NO_READS) + goto dumb; + + /* Try to seek to a block boundary, to improve kernel page management. */ + new_offset = offset & ~(fp->_IO_buf_end - fp->_IO_buf_base - 1); + delta = offset - new_offset; + if (delta > fp->_IO_buf_end - fp->_IO_buf_base) + { + new_offset = offset; + delta = 0; + } + result = _IO_SYSSEEK (fp, new_offset, 0); + if (result < 0) + return EOF; + if (delta == 0) + count = 0; + else + { + count = _IO_SYSREAD (fp, fp->_IO_buf_base, + (must_be_exact + ? delta : fp->_IO_buf_end - fp->_IO_buf_base)); + if (count < delta) + { + /* We weren't allowed to read, but try to seek the remainder. */ + offset = count == EOF ? delta : delta-count; + dir = _IO_seek_cur; + goto dumb; + } + } + _IO_setg (fp, fp->_IO_buf_base, fp->_IO_buf_base + delta, + fp->_IO_buf_base + count); + _IO_setp (fp, fp->_IO_buf_base, fp->_IO_buf_base); + fp->_offset = result + count; + _IO_mask_flags (fp, 0, _IO_EOF_SEEN); + return offset; + dumb: + + _IO_unsave_markers (fp); + result = _IO_SYSSEEK (fp, offset, dir); + if (result != EOF) + { + _IO_mask_flags (fp, 0, _IO_EOF_SEEN); + fp->_offset = result; + _IO_setg (fp, fp->_IO_buf_base, fp->_IO_buf_base, fp->_IO_buf_base); + _IO_setp (fp, fp->_IO_buf_base, fp->_IO_buf_base); + } + return result; + +resync: + /* We need to do it since it is possible that the file offset in + the kernel may be changed behind our back. It may happen when + we fopen a file and then do a fork. One process may access the + the file and the kernel file offset will be changed. */ + if (fp->_offset >= 0) + _IO_SYSSEEK (fp, fp->_offset, 0); + + return offset; +} + + +_IO_size_t +_IO_wfile_xsputn (f, data, n) + _IO_FILE *f; + const void *data; + _IO_size_t n; +{ + register const wchar_t *s = (const wchar_t *) data; + _IO_size_t to_do = n; + int must_flush = 0; + _IO_size_t count; + + if (n <= 0) + return 0; + /* This is an optimized implementation. + If the amount to be written straddles a block boundary + (or the filebuf is unbuffered), use sys_write directly. */ + + /* First figure out how much space is available in the buffer. */ + count = f->_wide_data->_IO_write_end - f->_wide_data->_IO_write_ptr; + if ((f->_flags & _IO_LINE_BUF) && (f->_flags & _IO_CURRENTLY_PUTTING)) + { + count = f->_wide_data->_IO_buf_end - f->_wide_data->_IO_write_ptr; + if (count >= n) + { + register const wchar_t *p; + for (p = s + n; p > s; ) + { + if (*--p == L'\n') + { + count = p - s + 1; + must_flush = 1; + break; + } + } + } + } + /* Then fill the buffer. */ + if (count > 0) + { + if (count > to_do) + count = to_do; + if (count > 20) + { +#ifdef _LIBC + f->_wide_data->_IO_write_ptr = + __wmempcpy (f->_wide_data->_IO_write_ptr, s, count); +#else + wmemcpy (f->_wide_data->_IO_write_ptr, s, count); + f->_wide_data->_IO_write_ptr += count; +#endif + s += count; + } + else + { + register wchar_t *p = f->_wide_data->_IO_write_ptr; + register int i = (int) count; + while (--i >= 0) + *p++ = *s++; + f->_wide_data->_IO_write_ptr = p; + } + to_do -= count; + } + if (to_do > 0) + to_do -= _IO_wdefault_xsputn (f, s, to_do); + if (must_flush + && f->_wide_data->_IO_write_ptr != f->_wide_data->_IO_write_base) + _IO_wdo_write (f, f->_wide_data->_IO_write_base, + f->_wide_data->_IO_write_ptr + - f->_wide_data->_IO_write_base); + + return n - to_do; +} + + +struct _IO_jump_t _IO_wfile_jumps = +{ + JUMP_INIT_DUMMY, + JUMP_INIT(finish, _IO_new_file_finish), + JUMP_INIT(overflow, (_IO_overflow_t) _IO_wfile_overflow), + JUMP_INIT(underflow, (_IO_underflow_t) _IO_wfile_underflow), + JUMP_INIT(uflow, (_IO_underflow_t) _IO_wdefault_uflow), + JUMP_INIT(pbackfail, _IO_default_pbackfail), + JUMP_INIT(xsputn, _IO_wfile_xsputn), + JUMP_INIT(xsgetn, _IO_file_xsgetn), + JUMP_INIT(seekoff, _IO_wfile_seekoff), + JUMP_INIT(seekpos, _IO_default_seekpos), + JUMP_INIT(setbuf, _IO_new_file_setbuf), + JUMP_INIT(sync, (_IO_sync_t) _IO_wfile_sync), + JUMP_INIT(doallocate, _IO_wfile_doallocate), + JUMP_INIT(read, _IO_file_read), + JUMP_INIT(write, _IO_new_file_write), + JUMP_INIT(seek, _IO_file_seek), + JUMP_INIT(close, _IO_file_close), + JUMP_INIT(stat, _IO_file_stat), + JUMP_INIT(showmanyc, _IO_default_showmanyc), + JUMP_INIT(imbue, _IO_default_imbue) +}; diff --git a/libio/wgenops.c b/libio/wgenops.c new file mode 100644 index 0000000000..496d080014 --- /dev/null +++ b/libio/wgenops.c @@ -0,0 +1,747 @@ +/* Copyright (C) 1993, 1995, 1997, 1998, 1999 Free Software Foundation, Inc. + This file is part of the GNU IO Library. + Written by Ulrich Drepper <drepper@cygnus.com>. + Based on the single byte version by Per Bothner <bothner@cygnus.com>. + + This library is free software; you can redistribute it and/or + modify it under the terms of the GNU General Public License as + published by the Free Software Foundation; either version 2, or (at + your option) any later version. + + This library is distributed in the hope that it will be useful, but + WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this library; see the file COPYING. If not, write to + the Free Software Foundation, 59 Temple Place - Suite 330, Boston, + MA 02111-1307, USA. + + As a special exception, if you link this library with files + compiled with a GNU compiler to produce an executable, this does + not cause the resulting executable to be covered by the GNU General + Public License. This exception does not however invalidate any + other reasons why the executable file might be covered by the GNU + General Public License. */ + +/* Generic or default I/O operations. */ + +#include "libioP.h" +#ifdef __STDC__ +#include <stdlib.h> +#endif +#include <string.h> +#include <wchar.h> + + + +static int save_for_wbackup __P ((_IO_FILE *fp, wchar_t *end_p)) +#ifdef _LIBC + internal_function +#endif + ; + +/* Return minimum _pos markers + Assumes the current get area is the main get area. */ +_IO_ssize_t _IO_least_wmarker __P ((_IO_FILE *fp, wchar_t *end_p)); + +_IO_ssize_t +_IO_least_wmarker (fp, end_p) + _IO_FILE *fp; + wchar_t *end_p; +{ + _IO_ssize_t least_so_far = end_p - fp->_wide_data->_IO_read_base; + struct _IO_marker *mark; + for (mark = fp->_markers; mark != NULL; mark = mark->_next) + if (mark->_pos < least_so_far) + least_so_far = mark->_pos; + return least_so_far; +} + +/* Switch current get area from backup buffer to (start of) main get area. */ +void +_IO_switch_to_main_wget_area (fp) + _IO_FILE *fp; +{ + wchar_t *tmp; + fp->_flags &= ~_IO_IN_BACKUP; + /* Swap _IO_read_end and _IO_save_end. */ + tmp = fp->_wide_data->_IO_read_end; + fp->_wide_data->_IO_read_end = fp->_wide_data->_IO_save_end; + fp->_wide_data->_IO_save_end= tmp; + /* Swap _IO_read_base and _IO_save_base. */ + tmp = fp->_wide_data->_IO_read_base; + fp->_wide_data->_IO_read_base = fp->_wide_data->_IO_save_base; + fp->_wide_data->_IO_save_base = tmp; + /* Set _IO_read_ptr. */ + fp->_wide_data->_IO_read_ptr = fp->_wide_data->_IO_read_base; +} + + +/* Switch current get area from main get area to (end of) backup area. */ +void +_IO_switch_to_wbackup_area (fp) + _IO_FILE *fp; +{ + wchar_t *tmp; + fp->_flags |= _IO_IN_BACKUP; + /* Swap _IO_read_end and _IO_save_end. */ + tmp = fp->_wide_data->_IO_read_end; + fp->_wide_data->_IO_read_end = fp->_wide_data->_IO_save_end; + fp->_wide_data->_IO_save_end = tmp; + /* Swap _IO_read_base and _IO_save_base. */ + tmp = fp->_wide_data->_IO_read_base; + fp->_wide_data->_IO_read_base = fp->_wide_data->_IO_save_base; + fp->_wide_data->_IO_save_base = tmp; + /* Set _IO_read_ptr. */ + fp->_wide_data->_IO_read_ptr = fp->_wide_data->_IO_read_end; +} + + +void +_IO_wsetb (f, b, eb, a) + _IO_FILE *f; + wchar_t *b; + wchar_t *eb; + int a; +{ + if (f->_wide_data->_IO_buf_base && !(f->_flags & _IO_USER_BUF)) + FREE_BUF (f->_wide_data->_IO_buf_base, _IO_wblen (f)); + f->_wide_data->_IO_buf_base = b; + f->_wide_data->_IO_buf_end = eb; + if (a) + f->_flags &= ~_IO_USER_BUF; + else + f->_flags |= _IO_USER_BUF; +} + + +wint_t +_IO_wdefault_pbackfail (fp, c) + _IO_FILE *fp; + wint_t c; +{ + if (fp->_wide_data->_IO_read_ptr > fp->_wide_data->_IO_read_base + && !_IO_in_backup (fp) + && (wint_t) fp->_IO_read_ptr[-1] == c) + --fp->_IO_read_ptr; + else + { + /* Need to handle a filebuf in write mode (switch to read mode). FIXME!*/ + if (!_IO_in_backup (fp)) + { + /* We need to keep the invariant that the main get area + logically follows the backup area. */ + if (fp->_wide_data->_IO_read_ptr > fp->_wide_data->_IO_read_base + && _IO_have_wbackup (fp)) + { + if (save_for_wbackup (fp, fp->_wide_data->_IO_read_ptr)) + return WEOF; + } + else if (!_IO_have_wbackup (fp)) + { + /* No backup buffer: allocate one. */ + /* Use nshort buffer, if unused? (probably not) FIXME */ + int backup_size = 128; + wchar_t *bbuf = (wchar_t *) malloc (backup_size + * sizeof (wchar_t)); + if (bbuf == NULL) + return WEOF; + fp->_wide_data->_IO_save_base = bbuf; + fp->_wide_data->_IO_save_end = (fp->_wide_data->_IO_save_base + + backup_size); + fp->_wide_data->_IO_backup_base = fp->_wide_data->_IO_save_end; + } + fp->_wide_data->_IO_read_base = fp->_wide_data->_IO_read_ptr; + _IO_switch_to_wbackup_area (fp); + } + else if (fp->_wide_data->_IO_read_ptr <= fp->_wide_data->_IO_read_base) + { + /* Increase size of existing backup buffer. */ + _IO_size_t new_size; + _IO_size_t old_size = (fp->_wide_data->_IO_read_end + - fp->_wide_data->_IO_read_base); + wchar_t *new_buf; + new_size = 2 * old_size; + new_buf = (wchar_t *) malloc (new_size * sizeof (wchar_t)); + if (new_buf == NULL) + return WEOF; + __wmemcpy (new_buf + (new_size - old_size), + fp->_wide_data->_IO_read_base, old_size); + free (fp->_wide_data->_IO_read_base); + _IO_wsetg (fp, new_buf, new_buf + (new_size - old_size), + new_buf + new_size); + fp->_wide_data->_IO_backup_base = fp->_wide_data->_IO_read_ptr; + } + + *--fp->_wide_data->_IO_read_ptr = c; + } + return c; +} + + +void +_IO_wdefault_finish (fp, dummy) + _IO_FILE *fp; + int dummy; +{ + struct _IO_marker *mark; + if (fp->_wide_data->_IO_buf_base && !(fp->_flags & _IO_USER_BUF)) + { + FREE_BUF (fp->_wide_data->_IO_buf_base, + _IO_wblen (fp) * sizeof (wchar_t)); + fp->_wide_data->_IO_buf_base = fp->_wide_data->_IO_buf_end = NULL; + } + + for (mark = fp->_markers; mark != NULL; mark = mark->_next) + mark->_sbuf = NULL; + + if (fp->_IO_save_base) + { + free (fp->_wide_data->_IO_save_base); + fp->_IO_save_base = NULL; + } + +#ifdef _IO_MTSAFE_IO + _IO_lock_fini (*fp->_lock); +#endif + + _IO_un_link (fp); +} + + +wint_t +_IO_wdefault_uflow (fp) + _IO_FILE *fp; +{ + wint_t wch; + wch = _IO_UNDERFLOW (fp); + if (wch == WEOF) + return WEOF; + return *fp->_wide_data->_IO_read_ptr++; +} + + +wint_t +__woverflow (f, wch) + _IO_FILE *f; + wint_t wch; +{ + if (f->_mode == 0) + _IO_fwide (f, 1); + return _IO_OVERFLOW (f, wch); +} + + +wint_t +__wuflow (fp) + _IO_FILE *fp; +{ + if (fp->_mode < 0 || (fp->_mode == 0 && _IO_fwide (fp, 1) != 1)) + return EOF; + + if (fp->_mode == 0) + _IO_fwide (fp, 1); + if (_IO_in_put_mode (fp)) + if (_IO_switch_to_get_mode (fp) == EOF) + return WEOF; + if (fp->_wide_data->_IO_read_ptr < fp->_wide_data->_IO_read_end) + return *fp->_wide_data->_IO_read_ptr++; + if (_IO_in_backup (fp)) + { + _IO_switch_to_main_wget_area (fp); + if (fp->_wide_data->_IO_read_ptr < fp->_wide_data->_IO_read_end) + return *fp->_wide_data->_IO_read_ptr++; + } + if (_IO_have_markers (fp)) + { + if (save_for_wbackup (fp, fp->_wide_data->_IO_read_end)) + return WEOF; + } + else if (_IO_have_wbackup (fp)) + _IO_free_wbackup_area (fp); + return _IO_UFLOW (fp); +} + + +wint_t +__wunderflow (fp) + _IO_FILE *fp; +{ + if (fp->_mode < 0 || (fp->_mode == 0 && _IO_fwide (fp, 1) != 1)) + return EOF; + + if (_IO_in_put_mode (fp)) + if (_IO_switch_to_wget_mode (fp) == WEOF) + return WEOF; + if (fp->_wide_data->_IO_read_ptr < fp->_wide_data->_IO_read_end) + return *fp->_wide_data->_IO_read_ptr; + if (_IO_in_backup (fp)) + { + _IO_switch_to_main_wget_area (fp); + if (fp->_wide_data->_IO_read_ptr < fp->_wide_data->_IO_read_end) + return *fp->_wide_data->_IO_read_ptr; + } + if (_IO_have_markers (fp)) + { + if (save_for_wbackup (fp, fp->_wide_data->_IO_read_end)) + return EOF; + } + else if (_IO_have_backup (fp)) + _IO_free_wbackup_area (fp); + return _IO_UNDERFLOW (fp); +} + + +_IO_size_t +_IO_wdefault_xsputn (f, data, n) + _IO_FILE *f; + const void *data; + _IO_size_t n; +{ + const wchar_t *s = (const wchar_t *) data; + _IO_size_t more = n; + if (more <= 0) + return 0; + for (;;) + { + /* Space available. */ + _IO_ssize_t count = (f->_wide_data->_IO_write_end + - f->_wide_data->_IO_write_ptr); + if (count > 0) + { + if ((_IO_size_t) count > more) + count = more; + if (count > 20) + { +#ifdef _LIBC + f->_wide_data->_IO_write_ptr = + __wmempcpy (f->_wide_data->_IO_write_ptr, s, count); +#else + memcpy (f->_wide_data->_IO_write_ptr, s, count); + f->_wide_data->_IO_write_ptr += count; +#endif + s += count; + } + else if (count <= 0) + count = 0; + else + { + wchar_t *p = f->_wide_data->_IO_write_ptr; + _IO_ssize_t i; + for (i = count; --i >= 0; ) + *p++ = *s++; + f->_wide_data->_IO_write_ptr = p; + } + more -= count; + } + if (more == 0 || __woverflow (f, *s++) == WEOF) + break; + more--; + } + return n - more; +} + + +_IO_size_t +_IO_wdefault_xsgetn (fp, data, n) + _IO_FILE *fp; + void *data; + _IO_size_t n; +{ + _IO_size_t more = n; + wchar_t *s = (wchar_t*) data; + for (;;) + { + /* Data available. */ + _IO_ssize_t count = (fp->_wide_data->_IO_read_end + - fp->_wide_data->_IO_read_ptr); + if (count > 0) + { + if ((_IO_size_t) count > more) + count = more; + if (count > 20) + { +#ifdef _LIBC + s = __wmempcpy (s, fp->_wide_data->_IO_read_ptr, count); +#else + memcpy (s, fp->_wide_data->_IO_read_ptr, count); + s += count; +#endif + fp->_wide_data->_IO_read_ptr += count; + } + else if (count <= 0) + count = 0; + else + { + wchar_t *p = fp->_wide_data->_IO_read_ptr; + int i = (int) count; + while (--i >= 0) + *s++ = *p++; + fp->_wide_data->_IO_read_ptr = p; + } + more -= count; + } + if (more == 0 || __wunderflow (fp) == WEOF) + break; + } + return n - more; +} + + +void +_IO_wdoallocbuf (fp) + _IO_FILE *fp; +{ + if (fp->_wide_data->_IO_buf_base) + return; + if (!(fp->_flags & _IO_UNBUFFERED)) + if (_IO_DOALLOCATE (fp) != WEOF) + return; + _IO_wsetb (fp, fp->_wide_data->_shortbuf, fp->_wide_data->_shortbuf + 1, 0); +} + + +_IO_FILE * +_IO_wdefault_setbuf (fp, p, len) + _IO_FILE *fp; + wchar_t *p; + _IO_ssize_t len; +{ + if (_IO_SYNC (fp) == EOF) + return NULL; + if (p == NULL || len == 0) + { + fp->_flags |= _IO_UNBUFFERED; + _IO_wsetb (fp, fp->_wide_data->_shortbuf, fp->_wide_data->_shortbuf + 1, + 0); + } + else + { + fp->_flags &= ~_IO_UNBUFFERED; + _IO_wsetb (fp, p, p + len, 0); + } + fp->_wide_data->_IO_write_base = fp->_wide_data->_IO_write_ptr + = fp->_wide_data->_IO_write_end = 0; + fp->_wide_data->_IO_read_base = fp->_wide_data->_IO_read_ptr + = fp->_wide_data->_IO_read_end = 0; + return fp; +} + + +int +_IO_wdefault_doallocate (fp) + _IO_FILE *fp; +{ + wchar_t *buf; + + ALLOC_WBUF (buf, _IO_BUFSIZ, EOF); + _IO_wsetb (fp, buf, buf + _IO_BUFSIZ, 1); + return 1; +} + + +int +_IO_switch_to_wget_mode (fp) + _IO_FILE *fp; +{ + if (fp->_wide_data->_IO_write_ptr > fp->_wide_data->_IO_write_base) + if (_IO_OVERFLOW (fp, EOF) == EOF) + return EOF; + if (_IO_in_backup (fp)) + fp->_wide_data->_IO_read_base = fp->_wide_data->_IO_backup_base; + else + { + fp->_wide_data->_IO_read_base = fp->_wide_data->_IO_buf_base; + if (fp->_wide_data->_IO_write_ptr > fp->_wide_data->_IO_read_end) + fp->_wide_data->_IO_read_end = fp->_wide_data->_IO_write_ptr; + } + fp->_wide_data->_IO_read_ptr = fp->_wide_data->_IO_write_ptr; + + fp->_wide_data->_IO_write_base = fp->_wide_data->_IO_write_ptr + = fp->_wide_data->_IO_write_end = fp->_wide_data->_IO_read_ptr; + + fp->_flags &= ~_IO_CURRENTLY_PUTTING; + return 0; +} + +void +_IO_free_wbackup_area (fp) + _IO_FILE *fp; +{ + if (_IO_in_backup (fp)) + _IO_switch_to_main_wget_area (fp); /* Just in case. */ + free (fp->_wide_data->_IO_save_base); + fp->_wide_data->_IO_save_base = NULL; + fp->_wide_data->_IO_save_end = NULL; + fp->_wide_data->_IO_backup_base = NULL; +} + +#if 0 +int +_IO_switch_to_wput_mode (fp) + _IO_FILE *fp; +{ + fp->_wide_data->_IO_write_base = fp->_wide_data->_IO_read_ptr; + fp->_wide_data->_IO_write_ptr = fp->_wide_data->_IO_read_ptr; + /* Following is wrong if line- or un-buffered? */ + fp->_wide_data->_IO_write_end = (fp->_flags & _IO_IN_BACKUP + ? fp->_wide_data->_IO_read_end + : fp->_wide_data->_IO_buf_end); + + fp->_wide_data->_IO_read_ptr = fp->_wide_data->_IO_read_end; + fp->_wide_data->_IO_read_base = fp->_wide_data->_IO_read_end; + + fp->_flags |= _IO_CURRENTLY_PUTTING; + return 0; +} +#endif + + +static int +#ifdef _LIBC +internal_function +#endif +save_for_wbackup (fp, end_p) + _IO_FILE *fp; + wchar_t *end_p; +{ + /* Append [_IO_read_base..end_p] to backup area. */ + _IO_ssize_t least_mark = _IO_least_wmarker (fp, end_p); + /* needed_size is how much space we need in the backup area. */ + _IO_size_t needed_size = ((end_p - fp->_wide_data->_IO_read_base) + - least_mark); + /* FIXME: Dubious arithmetic if pointers are NULL */ + _IO_size_t current_Bsize = (fp->_wide_data->_IO_save_end + - fp->_wide_data->_IO_save_base); + _IO_size_t avail; /* Extra space available for future expansion. */ + _IO_ssize_t delta; + struct _IO_marker *mark; + if (needed_size > current_Bsize) + { + wchar_t *new_buffer; + avail = 100; + new_buffer = (wchar_t *) malloc ((avail + needed_size) + * sizeof (wchar_t)); + if (new_buffer == NULL) + return EOF; /* FIXME */ + if (least_mark < 0) + { +#ifdef _LIBC + __wmempcpy (__wmempcpy (new_buffer + avail, + fp->_wide_data->_IO_save_end + least_mark, + -least_mark), + fp->_wide_data->_IO_read_base, + end_p - fp->_wide_data->_IO_read_base); +#else + memcpy (new_buffer + avail, + fp->_wide_data->_IO_save_end + least_mark, + -least_mark * sizeof (wchar_t)); + memcpy (new_buffer + avail - least_mark, + fp->_wide_data->_IO_read_base, + (end_p - fp->_wide_data->_IO_read_base) * sizeof (wchar_t)); +#endif + } + else + { +#ifdef _LIBC + __wmemcpy (new_buffer + avail, + fp->_wide_data->_IO_read_base + least_mark, + needed_size); +#else + memcpy (new_buffer + avail, + fp->_wide_data->_IO_read_base + least_mark, + needed_size * sizeof (wchar_t)); +#endif + } + if (fp->_wide_data->_IO_save_base) + free (fp->_wide_data->_IO_save_base); + fp->_wide_data->_IO_save_base = new_buffer; + fp->_wide_data->_IO_save_end = new_buffer + avail + needed_size; + } + else + { + avail = current_Bsize - needed_size; + if (least_mark < 0) + { +#ifdef _LIBC + __wmemmove (fp->_wide_data->_IO_save_base + avail, + fp->_wide_data->_IO_save_end + least_mark, + -least_mark); + __wmemcpy (fp->_wide_data->_IO_save_base + avail - least_mark, + fp->_wide_data->_IO_read_base, + end_p - fp->_wide_data->_IO_read_base); +#else + memmove (fp->_wide_data->_IO_save_base + avail, + fp->_wide_data->_IO_save_end + least_mark, + -least_mark * sizeof (wchar_t)); + memcpy (fp->_wide_data->_IO_save_base + avail - least_mark, + fp->_wide_data->_IO_read_base, + (end_p - fp->_wide_data->_IO_read_base) * sizeof (wchar_t)); +#endif + } + else if (needed_size > 0) +#ifdef _LIBC + __wmemcpy (fp->_wide_data->_IO_save_base + avail, + fp->_wide_data->_IO_read_base + least_mark, + needed_size); +#else + memcpy (fp->_wide_data->_IO_save_base + avail, + fp->_wide_data->_IO_read_base + least_mark, + needed_size * sizeof (wchar_t)); +#endif + } + fp->_wide_data->_IO_backup_base = fp->_wide_data->_IO_save_base + avail; + /* Adjust all the streammarkers. */ + delta = end_p - fp->_wide_data->_IO_read_base; + for (mark = fp->_markers; mark != NULL; mark = mark->_next) + mark->_pos -= delta; + return 0; +} + +wint_t +_IO_sputbackwc (fp, c) + _IO_FILE *fp; + wint_t c; +{ + wint_t result; + + if (fp->_wide_data->_IO_read_ptr > fp->_wide_data->_IO_read_base + && (wchar_t)fp->_wide_data->_IO_read_ptr[-1] == (wchar_t) c) + { + fp->_wide_data->_IO_read_ptr--; + result = c; + } + else + result = _IO_PBACKFAIL (fp, c); + + if (result != EOF) + fp->_flags &= ~_IO_EOF_SEEN; + + return result; +} + +wint_t +_IO_sungetwc (fp) + _IO_FILE *fp; +{ + int result; + + if (fp->_wide_data->_IO_read_ptr > fp->_wide_data->_IO_read_base) + { + fp->_wide_data->_IO_read_ptr--; + result = *fp->_wide_data->_IO_read_ptr; + } + else + result = _IO_PBACKFAIL (fp, EOF); + + if (result != WEOF) + fp->_flags &= ~_IO_EOF_SEEN; + + return result; +} + + +unsigned +_IO_adjust_wcolumn (start, line, count) + unsigned start; + const wchar_t *line; + int count; +{ + const wchar_t *ptr = line + count; + while (ptr > line) + if (*--ptr == L'\n') + return line + count - ptr - 1; + return start + count; +} + +void +_IO_init_wmarker (marker, fp) + struct _IO_marker *marker; + _IO_FILE *fp; +{ + marker->_sbuf = fp; + if (_IO_in_put_mode (fp)) + _IO_switch_to_get_mode (fp); + if (_IO_in_backup (fp)) + marker->_pos = fp->_wide_data->_IO_read_ptr - fp->_wide_data->_IO_read_end; + else + marker->_pos = (fp->_wide_data->_IO_read_ptr + - fp->_wide_data->_IO_read_base); + + /* Should perhaps sort the chain? */ + marker->_next = fp->_markers; + fp->_markers = marker; +} + +#define BAD_DELTA EOF + +/* Return difference between MARK and current position of MARK's stream. */ +int +_IO_wmarker_delta (mark) + struct _IO_marker *mark; +{ + int cur_pos; + if (mark->_sbuf == NULL) + return BAD_DELTA; + if (_IO_in_backup (mark->_sbuf)) + cur_pos = (mark->_sbuf->_wide_data->_IO_read_ptr + - mark->_sbuf->_wide_data->_IO_read_end); + else + cur_pos = (mark->_sbuf->_wide_data->_IO_read_ptr + - mark->_sbuf->_wide_data->_IO_read_base); + return mark->_pos - cur_pos; +} + +int +_IO_seekwmark (fp, mark, delta) + _IO_FILE *fp; + struct _IO_marker *mark; + int delta; +{ + if (mark->_sbuf != fp) + return EOF; + if (mark->_pos >= 0) + { + if (_IO_in_backup (fp)) + _IO_switch_to_main_wget_area (fp); + fp->_wide_data->_IO_read_ptr = (fp->_wide_data->_IO_read_base + + mark->_pos); + } + else + { + if (!_IO_in_backup (fp)) + _IO_switch_to_wbackup_area (fp); + fp->_wide_data->_IO_read_ptr = fp->_wide_data->_IO_read_end + mark->_pos; + } + return 0; +} + +void +_IO_unsave_wmarkers (fp) + _IO_FILE *fp; +{ + struct _IO_marker *mark = fp->_markers; + if (mark) + { +#ifdef TODO + streampos offset = seekoff (0, ios::cur, ios::in); + if (offset != EOF) + { + offset += eGptr () - Gbase (); + for ( ; mark != NULL; mark = mark->_next) + mark->set_streampos (mark->_pos + offset); + } + else + { + for ( ; mark != NULL; mark = mark->_next) + mark->set_streampos (EOF); + } +#endif + fp->_markers = 0; + } + + if (_IO_have_backup (fp)) + _IO_free_wbackup_area (fp); +} diff --git a/libio/wprintf.c b/libio/wprintf.c new file mode 100644 index 0000000000..6fb6c32554 --- /dev/null +++ b/libio/wprintf.c @@ -0,0 +1,35 @@ +/* Copyright (C) 1991, 1995, 1996, 1997, 1999 Free Software Foundation, Inc. + This file is part of the GNU C Library. + + The GNU C Library is free software; you can redistribute it and/or + modify it under the terms of the GNU Library General Public License as + published by the Free Software Foundation; either version 2 of the + License, or (at your option) any later version. + + The GNU C Library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Library General Public License for more details. + + You should have received a copy of the GNU Library General Public + License along with the GNU C Library; see the file COPYING.LIB. If not, + write to the Free Software Foundation, Inc., 59 Temple Place - Suite 330, + Boston, MA 02111-1307, USA. */ + +#include <stdarg.h> +#include <stdio.h> + +/* Write formatted output to stdout from the format string FORMAT. */ +/* VARARGS1 */ +int +wprintf (const wchar_t *format, ...) +{ + va_list arg; + int done; + + va_start (arg, format); + done = vfwprintf (stdout, format, arg); + va_end (arg); + + return done; +} diff --git a/libio/wscanf.c b/libio/wscanf.c new file mode 100644 index 0000000000..a530d6fcfa --- /dev/null +++ b/libio/wscanf.c @@ -0,0 +1,36 @@ +/* Copyright (C) 1991, 1995, 1996, 1997, 1999 Free Software Foundation, Inc. + This file is part of the GNU C Library. + + The GNU C Library is free software; you can redistribute it and/or + modify it under the terms of the GNU Library General Public License as + published by the Free Software Foundation; either version 2 of the + License, or (at your option) any later version. + + The GNU C Library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Library General Public License for more details. + + You should have received a copy of the GNU Library General Public + License along with the GNU C Library; see the file COPYING.LIB. If not, + write to the Free Software Foundation, Inc., 59 Temple Place - Suite 330, + Boston, MA 02111-1307, USA. */ + +#include <stdarg.h> +#include <stdio.h> + + +/* Read formatted input from stdin according to the format string FORMAT. */ +/* VARARGS1 */ +int +wscanf (const wchar_t *format, ...) +{ + va_list arg; + int done; + + va_start (arg, format); + done = _IO_vfwscanf (stdin, format, arg, NULL); + va_end (arg); + + return done; +} diff --git a/libio/wstrops.c b/libio/wstrops.c new file mode 100644 index 0000000000..af2c957b05 --- /dev/null +++ b/libio/wstrops.c @@ -0,0 +1,330 @@ +/* Copyright (C) 1993, 1997, 1998, 1999 Free Software Foundation, Inc. + This file is part of the GNU IO Library. + + This library is free software; you can redistribute it and/or + modify it under the terms of the GNU General Public License as + published by the Free Software Foundation; either version 2, or (at + your option) any later version. + + This library is distributed in the hope that it will be useful, but + WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this library; see the file COPYING. If not, write to + the Free Software Foundation, 59 Temple Place - Suite 330, Boston, + MA 02111-1307, USA. + + As a special exception, if you link this library with files + compiled with a GNU compiler to produce an executable, this does + not cause the resulting executable to be covered by the GNU General + Public License. This exception does not however invalidate any + other reasons why the executable file might be covered by the GNU + General Public License. */ + +#include "strfile.h" +#include "libioP.h" +#include <string.h> +#include <wchar.h> + +#if 0 +/* The following definitions are for exposition only. + They map the terminology used in the ANSI/ISO C++ draft standard + to the implementation. */ + +/* allocated: set when a dynamic array object has been allocated, and + hence should be freed by the destructor for the strstreambuf object. */ +#define ALLOCATED(FP) ((FP)->_f._IO_buf_base && DYNAMIC(FP)) + +/* constant: set when the array object has const elements, + so the output sequence cannot be written. */ +#define CONSTANT(FP) ((FP)->_f._IO_file_flags & _IO_NO_WRITES) + +/* alsize: the suggested minimum size for a dynamic array object. */ +#define ALSIZE(FP) ??? /* not stored */ + +/* palloc: points to the function to call to allocate a dynamic array object.*/ +#define PALLOC(FP) \ + ((FP)->_s._allocate_buffer == default_alloc ? 0 : (FP)->_s._allocate_buffer) + +/* pfree: points to the function to call to free a dynamic array object. */ +#define PFREE(FP) \ + ((FP)->_s._free_buffer == default_free ? 0 : (FP)->_s._free_buffer) + +#endif + +#ifdef TODO +/* An "unbounded buffer" is when a buffer is supplied, but with no + specified length. An example is the buffer argument to sprintf. + */ +#endif + +void +_IO_wstr_init_static (fp, ptr, size, pstart) + _IO_FILE *fp; + wchar_t *ptr; + int size; + wchar_t *pstart; +{ + if (size == 0) + size = __wcslen (ptr); + else if (size < 0) + { + /* If size is negative 'the characters are assumed to + continue indefinitely.' This is kind of messy ... */ + int s; + size = 512; + /* Try increasing powers of 2, as long as we don't wrap around. */ + for (; s = 2*size, s > 0 && ptr + s > ptr && s < 0x4000000L; ) + size = s; + /* Try increasing size as much as we can without wrapping around. */ + for (s = size >> 1; s > 0; s >>= 1) + { + if (ptr + size + s > ptr) + size += s; + } + } + _IO_wsetb (fp, ptr, ptr + size, 0); + + fp->_wide_data->_IO_write_base = ptr; + fp->_wide_data->_IO_read_base = ptr; + fp->_wide_data->_IO_read_ptr = ptr; + if (pstart) + { + fp->_wide_data->_IO_write_ptr = pstart; + fp->_wide_data->_IO_write_end = ptr + size; + fp->_wide_data->_IO_read_end = pstart; + } + else + { + fp->_wide_data->_IO_write_ptr = ptr; + fp->_wide_data->_IO_write_end = ptr; + fp->_wide_data->_IO_read_end = ptr + size; + } + /* A null _allocate_buffer function flags the strfile as being static. */ + (((_IO_strfile *) fp)->_s._allocate_buffer) = (_IO_alloc_type)0; +} + +void +_IO_wstr_init_readonly (fp, ptr, size) + _IO_FILE *fp; + const char *ptr; + int size; +{ + _IO_wstr_init_static (fp, (wchar_t *) ptr, size, NULL); + fp->_IO_file_flags |= _IO_NO_WRITES; +} + +_IO_wint_t +_IO_wstr_overflow (fp, c) + _IO_FILE *fp; + _IO_wint_t c; +{ + int flush_only = c == WEOF; + _IO_size_t pos; + if (fp->_flags & _IO_NO_WRITES) + return flush_only ? 0 : WEOF; + if ((fp->_flags & _IO_TIED_PUT_GET) && !(fp->_flags & _IO_CURRENTLY_PUTTING)) + { + fp->_flags |= _IO_CURRENTLY_PUTTING; + fp->_wide_data->_IO_write_ptr = fp->_wide_data->_IO_read_ptr; + fp->_wide_data->_IO_read_ptr = fp->_wide_data->_IO_read_end; + } + pos = fp->_wide_data->_IO_write_ptr - fp->_wide_data->_IO_write_base; + if (pos >= (_IO_size_t) (_IO_wblen (fp) + flush_only)) + { + if (fp->_flags & _IO_USER_BUF) /* not allowed to enlarge */ + return WEOF; + else + { + wchar_t *new_buf; + wchar_t *old_buf = fp->_wide_data->_IO_buf_base; + _IO_size_t new_size = 2 * _IO_wblen (fp) + 100; + new_buf + = (wchar_t *) (*((_IO_strfile *) fp)->_s._allocate_buffer) (new_size + * sizeof (wchar_t)); + if (new_buf == NULL) + { + /* __ferror(fp) = 1; */ + return WEOF; + } + if (old_buf) + { + __wmemcpy (new_buf, old_buf, _IO_wblen (fp)); + (*((_IO_strfile *) fp)->_s._free_buffer) (old_buf); + /* Make sure _IO_setb won't try to delete _IO_buf_base. */ + fp->_wide_data->_IO_buf_base = NULL; + } + _IO_wsetb (fp, new_buf, new_buf + new_size, 1); + fp->_wide_data->_IO_read_base = + new_buf + (fp->_wide_data->_IO_read_base - old_buf); + fp->_wide_data->_IO_read_ptr = + new_buf + (fp->_wide_data->_IO_read_ptr - old_buf); + fp->_wide_data->_IO_read_end = + new_buf + (fp->_wide_data->_IO_read_end - old_buf); + fp->_wide_data->_IO_write_ptr = + new_buf + (fp->_wide_data->_IO_write_ptr - old_buf); + + fp->_wide_data->_IO_write_base = new_buf; + fp->_wide_data->_IO_write_end = fp->_wide_data->_IO_buf_end; + } + } + + if (!flush_only) + *fp->_wide_data->_IO_write_ptr++ = c; + if (fp->_wide_data->_IO_write_ptr > fp->_wide_data->_IO_read_end) + fp->_wide_data->_IO_read_end = fp->_wide_data->_IO_write_ptr; + return c; +} + +_IO_wint_t +_IO_wstr_underflow (fp) + _IO_FILE *fp; +{ + if (fp->_wide_data->_IO_write_ptr > fp->_wide_data->_IO_read_end) + fp->_wide_data->_IO_read_end = fp->_wide_data->_IO_write_ptr; + if ((fp->_flags & _IO_TIED_PUT_GET) && (fp->_flags & _IO_CURRENTLY_PUTTING)) + { + fp->_flags &= ~_IO_CURRENTLY_PUTTING; + fp->_wide_data->_IO_read_ptr = fp->_wide_data->_IO_write_ptr; + fp->_wide_data->_IO_write_ptr = fp->_wide_data->_IO_write_end; + } + if (fp->_wide_data->_IO_read_ptr < fp->_wide_data->_IO_read_end) + return *fp->_wide_data->_IO_read_ptr; + else + return WEOF; +} + +/* The size of the valid part of the buffer. */ + +_IO_ssize_t +_IO_wstr_count (fp) + _IO_FILE *fp; +{ + return ((fp->_wide_data->_IO_write_ptr > fp->_wide_data->_IO_read_end + ? fp->_wide_data->_IO_write_ptr : fp->_wide_data->_IO_read_end) + - fp->_wide_data->_IO_read_base); +} + +_IO_off64_t +_IO_wstr_seekoff (fp, offset, dir, mode) + _IO_FILE *fp; + _IO_off64_t offset; + int dir; + int mode; +{ + _IO_off64_t new_pos; + + if (mode == 0 && (fp->_flags & _IO_TIED_PUT_GET)) + mode = (fp->_flags & _IO_CURRENTLY_PUTTING ? _IOS_OUTPUT : _IOS_INPUT); + + if (mode == 0) + { + /* Don't move any pointers. But there is no clear indication what + mode FP is in. Let's guess. */ + if (fp->_IO_file_flags & _IO_NO_WRITES) + new_pos = fp->_wide_data->_IO_read_ptr - fp->_wide_data->_IO_read_base; + else + new_pos = (fp->_wide_data->_IO_write_ptr + - fp->_wide_data->_IO_write_base); + } + else + { + _IO_ssize_t cur_size = _IO_wstr_count (fp); + new_pos = EOF; + + /* Move the get pointer, if requested. */ + if (mode & _IOS_INPUT) + { + switch (dir) + { + case _IO_seek_end: + offset += cur_size; + break; + case _IO_seek_cur: + offset += (fp->_wide_data->_IO_read_ptr + - fp->_wide_data->_IO_read_base); + break; + default: /* case _IO_seek_set: */ + break; + } + if (offset < 0 || (_IO_ssize_t) offset > cur_size) + return EOF; + fp->_wide_data->_IO_read_ptr = (fp->_wide_data->_IO_read_base + + offset); + fp->_wide_data->_IO_read_end = (fp->_wide_data->_IO_read_base + + cur_size); + new_pos = offset; + } + + /* Move the put pointer, if requested. */ + if (mode & _IOS_OUTPUT) + { + switch (dir) + { + case _IO_seek_end: + offset += cur_size; + break; + case _IO_seek_cur: + offset += (fp->_wide_data->_IO_write_ptr + - fp->_wide_data->_IO_write_base); + break; + default: /* case _IO_seek_set: */ + break; + } + if (offset < 0 || (_IO_ssize_t) offset > cur_size) + return EOF; + fp->_wide_data->_IO_write_ptr = (fp->_wide_data->_IO_write_base + + offset); + new_pos = offset; + } + } + return new_pos; +} + +_IO_wint_t +_IO_wstr_pbackfail (fp, c) + _IO_FILE *fp; + _IO_wint_t c; +{ + if ((fp->_flags & _IO_NO_WRITES) && c != EOF) + return WEOF; + return _IO_wdefault_pbackfail (fp, c); +} + +void +_IO_wstr_finish (fp, dummy) + _IO_FILE *fp; + int dummy; +{ + if (fp->_wide_data->_IO_buf_base && !(fp->_flags & _IO_USER_BUF)) + (((_IO_strfile *) fp)->_s._free_buffer) (fp->_wide_data->_IO_buf_base); + fp->_wide_data->_IO_buf_base = NULL; + + _IO_wdefault_finish (fp, 0); +} + +struct _IO_jump_t _IO_wstr_jumps = +{ + JUMP_INIT_DUMMY, + JUMP_INIT(finish, _IO_wstr_finish), + JUMP_INIT(overflow, (_IO_overflow_t) _IO_wstr_overflow), + JUMP_INIT(underflow, (_IO_underflow_t) _IO_wstr_underflow), + JUMP_INIT(uflow, (_IO_underflow_t) _IO_wdefault_uflow), + JUMP_INIT(pbackfail, (_IO_pbackfail_t) _IO_wstr_pbackfail), + JUMP_INIT(xsputn, _IO_wdefault_xsputn), + JUMP_INIT(xsgetn, _IO_wdefault_xsgetn), + JUMP_INIT(seekoff, _IO_wstr_seekoff), + JUMP_INIT(seekpos, _IO_default_seekpos), + JUMP_INIT(setbuf, (_IO_setbuf_t) _IO_wdefault_setbuf), + JUMP_INIT(sync, _IO_default_sync), + JUMP_INIT(doallocate, _IO_wdefault_doallocate), + JUMP_INIT(read, _IO_default_read), + JUMP_INIT(write, _IO_default_write), + JUMP_INIT(seek, _IO_default_seek), + JUMP_INIT(close, _IO_default_close), + JUMP_INIT(stat, _IO_default_stat), + JUMP_INIT(showmanyc, _IO_default_showmanyc), + JUMP_INIT(imbue, _IO_default_imbue) +}; |