diff options
author | Roland McGrath <roland@gnu.org> | 1995-11-20 03:48:11 +0000 |
---|---|---|
committer | Roland McGrath <roland@gnu.org> | 1995-11-20 03:48:11 +0000 |
commit | 96aa2d94a2355cdc55c96e808d14a0e7f2ebe77d (patch) | |
tree | f7c87e6742af0707b858a1387ca85b679aa8d13e | |
parent | Fri Nov 17 17:57:00 1995 Roland McGrath <roland@churchy.gnu.ai.mit.edu> (diff) | |
download | glibc-96aa2d94a2355cdc55c96e808d14a0e7f2ebe77d.tar.gz glibc-96aa2d94a2355cdc55c96e808d14a0e7f2ebe77d.tar.bz2 glibc-96aa2d94a2355cdc55c96e808d14a0e7f2ebe77d.zip |
Sat Nov 18 16:46:01 1995 Ulrich Drepper <drepper@gnu.ai.mit.edu>
* libio/Makefile, libio/cleanup.c, libio/clearerr.c, libio/feof.c,
libio/ferror.c, libio/fgetc.c, libio/filedoalloc.c, libio/fileno.c,
libio/fileops.c, libio/fputc.c, libio/freopen.c, libio/fseek.c,
libio/genops.c, libio/getc.c, libio/getchar.c, libio/iofclose.c,
libio/iofdopen.c, libio/iofflush.c, libio/iofgetpos.c, libio/iofgets.c,
libio/iofopen.c, libio/iofprintf.c, libio/iofputs.c, libio/iofread.c,
libio/iofscanf.c, libio/iofsetpos.c, libio/ioftell.c, libio/iofwrite.c,
libio/iogetdelim.c, libio/iogetline.c, libio/iogets.c, libio/iolibio.h,
libio/iopadn.c, libio/ioprims.c, libio/ioputs.c, libio/ioseekoff.c,
libio/ioseekpos.c, libio/iosetbuffer.c, libio/iosetvbuf.c,
libio/iosprintf.c, libio/ioungetc.c, libio/iovsprintf.c,
libio/iovsscanf.c, libio/libio.h, libio/libioP.h, libio/putc.c,
libio/putchar.c, libio/rewind.c, libio/setbuf.c, libio/setlinebuf.c,
libio/stdfiles.c, libio/stdio.c, libio/stdio.h, libio/strfile.h,
libio/strops.c, libio/vasprintf.c, libio/vscanf.c, libio/vsnprintf.c:
New files. Slightly modified version from Linux libc.
* libio/memstream.c, libio/vdprintf.c: New files for functions not
(yet) part of GNU libio.
* libio/iofopncook.c: Implementation of `fopencookie', mainly written
by Per Bothner.
* stdio-common/getline.c: Adapted to libio.
* stdio-common/snprintf.c: Adapted to libio.
* stdio-common/vfprintf.c: Adapted to libio.
* stdio-common/vfscanf.c: Adapted to libio.
* sysdeps/posix/tempname.c: Adapted to libio.
74 files changed, 5783 insertions, 112 deletions
@@ -1,3 +1,34 @@ +Sat Nov 18 16:46:01 1995 Ulrich Drepper <drepper@gnu.ai.mit.edu> + + * libio/Makefile, libio/cleanup.c, libio/clearerr.c, libio/feof.c, + libio/ferror.c, libio/fgetc.c, libio/filedoalloc.c, libio/fileno.c, + libio/fileops.c, libio/fputc.c, libio/freopen.c, libio/fseek.c, + libio/genops.c, libio/getc.c, libio/getchar.c, libio/iofclose.c, + libio/iofdopen.c, libio/iofflush.c, libio/iofgetpos.c, libio/iofgets.c, + libio/iofopen.c, libio/iofprintf.c, libio/iofputs.c, libio/iofread.c, + libio/iofscanf.c, libio/iofsetpos.c, libio/ioftell.c, libio/iofwrite.c, + libio/iogetdelim.c, libio/iogetline.c, libio/iogets.c, libio/iolibio.h, + libio/iopadn.c, libio/ioprims.c, libio/ioputs.c, libio/ioseekoff.c, + libio/ioseekpos.c, libio/iosetbuffer.c, libio/iosetvbuf.c, + libio/iosprintf.c, libio/ioungetc.c, libio/iovsprintf.c, + libio/iovsscanf.c, libio/libio.h, libio/libioP.h, libio/putc.c, + libio/putchar.c, libio/rewind.c, libio/setbuf.c, libio/setlinebuf.c, + libio/stdfiles.c, libio/stdio.c, libio/stdio.h, libio/strfile.h, + libio/strops.c, libio/vasprintf.c, libio/vscanf.c, libio/vsnprintf.c: + New files. Slightly modified version from Linux libc. + + * libio/memstream.c, libio/vdprintf.c: New files for functions not + (yet) part of GNU libio. + + * libio/iofopncook.c: Implementation of `fopencookie', mainly written + by Per Bothner. + + * stdio-common/getline.c: Adapted to libio. + * stdio-common/snprintf.c: Adapted to libio. + * stdio-common/vfprintf.c: Adapted to libio. + * stdio-common/vfscanf.c: Adapted to libio. + * sysdeps/posix/tempname.c: Adapted to libio. + Fri Nov 17 17:57:00 1995 Roland McGrath <roland@churchy.gnu.ai.mit.edu> * sysdeps/generic/Makefile (make_siglist): Add missing backslash. diff --git a/Makeconfig b/Makeconfig index a610d057f5..6b403a1694 100644 --- a/Makeconfig +++ b/Makeconfig @@ -411,9 +411,12 @@ endif # gcc # files (including ones given in angle brackets) in the current directory # and in the parent library source directory. # `+sysdep-includes' will be defined by Makerules. -+includes = -I. $(filter-out -I,-I$(patsubst %/,%,$(..))) \ ++includes = -I. $(filter-out -I,-I$(patsubst %/,%,$(..))) $($(stdio)-include) \ $(includes) $(+sysdep-includes) $(last-includes) +# Since libio has several internal header files, we use a -I instead +# of many little headers in the top level source directory. +libio-include = -I$(..)libio # These are the variables that the implicit compilation rules use. CPPFLAGS = $(+includes) $(defines) -include $(..)libc-symbols.h \ diff --git a/configure.in b/configure.in index 6b2624e254..e35769afb2 100644 --- a/configure.in +++ b/configure.in @@ -55,7 +55,7 @@ AC_ARG_WITH(weak-symbols, dnl AC_ARG_ENABLE(libio, dnl [ --enable-libio build in GNU libio instead of GNU stdio], - stdio=libio, stdio=stdio) + stdio=libio, stdio=default) dnl Arguments to enable or disable building the shared, profiled, and dnl -fomit-frame-pointer libraries. @@ -69,13 +69,6 @@ AC_ARG_ENABLE(omitfp, dnl [ --enable-omitfp build undebuggable optimized library [default=no]], omitfp=$enableval, omitfp=no) -AC_MSG_CHECKING(stdio selection) -AC_SUBST(stdio) -if test $stdio = libio; then - AC_DEFINE(USE_IN_LIBIO) -fi -AC_MSG_RESULT($stdio) - AC_CANONICAL_HOST # We keep the original values in `$config_*' and never modify them, so we # can write them unchanged into config.make. Everything else uses @@ -486,6 +479,14 @@ else config_uname= fi +AC_MSG_CHECKING(stdio selection) +AC_SUBST(stdio) +case $stdio in +libio) AC_DEFINE(USE_IN_LIBIO) ;; +default) stdio=stdio ;; +esac +AC_MSG_RESULT($stdio) + AC_SUBST(gnu_ld) AC_SUBST(gnu_as) AC_SUBST(elf) AC_SUBST(weak) if test $gnu_ld = yes; then AC_DEFINE(HAVE_GNU_LD) diff --git a/hurd/hurdfault.c b/hurd/hurdfault.c index e1f8c19acc..5aedc582ce 100644 --- a/hurd/hurdfault.c +++ b/hurd/hurdfault.c @@ -26,6 +26,7 @@ Cambridge, MA 02139, USA. */ #include <stdio.h> #include "thread_state.h" #include "faultexc.h" /* mig-generated header for our exc server. */ +#include <assert.h> jmp_buf _hurdsig_fault_env; @@ -121,7 +122,7 @@ _hurdsig_fault_init (void) MACH_PORT_RIGHT_RECEIVE, &forward_sigexc); assert_perror (err); - err = __mach_port_insert_right (__mach_task_self (), + err = __mach_port_insert_right (__mach_task_self (), sigexc, sigexc, MACH_MSG_TYPE_MAKE_SEND); assert_perror (err); err = __thread_set_special_port (_hurd_msgport_thread, diff --git a/libio/Makefile b/libio/Makefile new file mode 100644 index 0000000000..8d09a5ecce --- /dev/null +++ b/libio/Makefile @@ -0,0 +1,44 @@ +# Copyright (C) 1995 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., 675 Mass Ave, +# Cambridge, MA 02139, USA. + +# +# Specific makefile for libio. +# +subdir := libio + +headers := stdio.h libio.h + +routines := \ + filedoalloc iofclose iofdopen iofflush iofgetpos iofgets iofopen \ + iofopncook iofprintf iofputs iofread iofscanf iofsetpos ioftell \ + iofwrite iogetdelim iogetline iogets iopadn ioprims ioputs \ + ioseekoff ioseekpos iosetbuffer iosetvbuf iosprintf ioungetc \ + iovsprintf iovsscanf \ + \ + clearerr feof ferror fgetc fileno fputc freopen fseek getc getchar \ + memstream putc putchar rewind setbuf setlinebuf vasprintf vdprintf \ + vscanf vsnprintf \ + \ + libc_fatal + +aux := \ + cleanup fileops genops stdfiles stdio strops + +distribute := iolibio.h libioP.h strfile.h + +include ../Rules diff --git a/libio/cleanup.c b/libio/cleanup.c new file mode 100644 index 0000000000..b4c8be927f --- /dev/null +++ b/libio/cleanup.c @@ -0,0 +1,15 @@ +#include "libioP.h" +#if _G_HAVE_ATEXIT +#include <stdlib.h> + +typedef void (*voidfunc) __P((void)); + +static void +DEFUN_VOID(_IO_register_cleanup) +{ + atexit ((voidfunc)_IO_cleanup); + _IO_cleanup_registration_needed = 0; +} + +void (*_IO_cleanup_registration_needed)() = _IO_register_cleanup; +#endif /* _G_HAVE_ATEXIT */ diff --git a/libio/clearerr.c b/libio/clearerr.c new file mode 100644 index 0000000000..ee9780bdaf --- /dev/null +++ b/libio/clearerr.c @@ -0,0 +1,10 @@ +#include "libioP.h" +#include "stdio.h" + +void +clearerr(fp) + FILE* fp; +{ + CHECK_FILE(fp, /*nothing*/); + _IO_clearerr(fp); +} diff --git a/libio/feof.c b/libio/feof.c new file mode 100644 index 0000000000..bd30c175f3 --- /dev/null +++ b/libio/feof.c @@ -0,0 +1,34 @@ +/* +Copyright (C) 1993 Free Software Foundation + +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" + +int +feof(fp) + _IO_FILE* fp; +{ + CHECK_FILE(fp, EOF); + return _IO_feof(fp); +} diff --git a/libio/ferror.c b/libio/ferror.c new file mode 100644 index 0000000000..d0159818e8 --- /dev/null +++ b/libio/ferror.c @@ -0,0 +1,34 @@ +/* +Copyright (C) 1993, 1995 Free Software Foundation + +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" + +int +ferror (fp) + _IO_FILE* fp; +{ + CHECK_FILE (fp, EOF); + return _IO_ferror (fp); +} diff --git a/libio/fgetc.c b/libio/fgetc.c new file mode 100644 index 0000000000..19c0a589d9 --- /dev/null +++ b/libio/fgetc.c @@ -0,0 +1,34 @@ +/* +Copyright (C) 1993, 1995 Free Software Foundation + +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" + +int +fgetc (fp) + FILE *fp; +{ + CHECK_FILE (fp, EOF); + return _IO_getc (fp); +} diff --git a/libio/filedoalloc.c b/libio/filedoalloc.c new file mode 100644 index 0000000000..8ab1738a7c --- /dev/null +++ b/libio/filedoalloc.c @@ -0,0 +1,103 @@ +/* +Copyright (C) 1993 Free Software Foundation + +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. */ + +#define _POSIX_SOURCE +#include "libioP.h" +#include <sys/types.h> +#include <sys/stat.h> +#ifdef __STDC__ +#include <stdlib.h> +#endif + +/* If this function pointer is non-zero, we should call it. + It's supposed to make sure _IO_cleanup gets called on exit. + We call it from _IO_file_doallocate, since that is likely + to get called by any program that does buffered I/O. */ +void (*_IO_cleanup_registration_needed)(); + +/* + * 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 +DEFUN(_IO_file_doallocate, (fp), + register _IO_FILE *fp) +{ + register _IO_size_t size; + int couldbetty; + register char *p; + struct stat st; + + if (_IO_cleanup_registration_needed) + (*_IO_cleanup_registration_needed)(); + + if (fp->_fileno < 0 || _IO_SYSSTAT (fp, &st) < 0) + { + couldbetty = 0; + size = _IO_BUFSIZ; +#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; +#else + size = _IO_BUFSIZ; +#endif + } + p = ALLOC_BUF(size); + if (p == NULL) + return EOF; + _IO_setb(fp, p, p+size, 1); + if (couldbetty && isatty(fp->_fileno)) + fp->_flags |= _IO_LINE_BUF; + return 1; +} diff --git a/libio/fileno.c b/libio/fileno.c new file mode 100644 index 0000000000..fbea4d4995 --- /dev/null +++ b/libio/fileno.c @@ -0,0 +1,38 @@ +/* +Copyright (C) 1993, 1995 Free Software Foundation + +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" + +int +fileno (fp) + _IO_FILE* fp; +{ + CHECK_FILE (fp, EOF); + + if (!(fp->_flags & _IO_IS_FILEBUF)) + return EOF; + + return _IO_fileno (fp); +} diff --git a/libio/fileops.c b/libio/fileops.c new file mode 100644 index 0000000000..89381ec699 --- /dev/null +++ b/libio/fileops.c @@ -0,0 +1,738 @@ +/* +Copyright (C) 1993, 1995 Free Software Foundation + +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. */ + +/* written by Per Bothner (bothner@cygnus.com) */ + +#define _POSIX_SOURCE +#include "libioP.h" +#include <fcntl.h> +#include <sys/types.h> +#include <sys/stat.h> +#include <string.h> +#include <errno.h> +#ifndef errno +extern int errno; +#endif + +/* An fstream can be in at most one of put mode, get mode, or putback mode. + Putback mode is a variant of get mode. + + In a filebuf, there is only one current position, instead of two + separate get and put pointers. In get mode, the current posistion + is that of gptr(); in put mode that of pptr(). + + The position in the buffer that corresponds to the position + in external file system is file_ptr(). + This is normally _IO_read_end, except in putback mode, + when it is _IO_save_end. + If the field _fb._offset is >= 0, it gives the offset in + the file as a whole corresponding to eGptr(). (?) + + PUT MODE: + If a filebuf is in put mode, pbase() is non-NULL and equal to base(). + Also, epptr() == ebuf(). + Also, eback() == gptr() && gptr() == egptr(). + The un-flushed character are those between pbase() and pptr(). + GET MODE: + If a filebuf is in get or putback mode, eback() != egptr(). + In get mode, the unread characters are between gptr() and egptr(). + The OS file position corresponds to that of egptr(). + PUTBACK MODE: + Putback mode is used to remember "excess" characters that have + been sputbackc'd in a separate putback buffer. + In putback mode, the get buffer points to the special putback buffer. + The unread characters are the characters between gptr() and egptr() + in the putback buffer, as well as the area between save_gptr() + and save_egptr(), which point into the original reserve buffer. + (The pointers save_gptr() and save_egptr() are the values + of gptr() and egptr() at the time putback mode was entered.) + The OS position corresponds to that of save_egptr(). + + LINE BUFFERED OUTPUT: + During line buffered output, pbase()==base() && epptr()==base(). + However, ptr() may be anywhere between base() and ebuf(). + This forces a call to filebuf::overflow(int C) on every put. + If there is more space in the buffer, and C is not a '\n', + then C is inserted, and pptr() incremented. + + UNBUFFERED STREAMS: + If a filebuf is unbuffered(), the _shortbuf[1] is used as the buffer. +*/ + +#define CLOSED_FILEBUF_FLAGS \ + (_IO_IS_FILEBUF+_IO_NO_READS+_IO_NO_WRITES+_IO_TIED_PUT_GET) + + +void +DEFUN(_IO_file_init, (fp), + register _IO_FILE *fp) +{ + /* POSIX.1 allows another file handle to be used to change the position + of our file descriptor. Hence we actually don't know the actual + position before we do the first fseek (and until a following fflush). */ + fp->_offset = _IO_pos_BAD; + fp->_IO_file_flags |= CLOSED_FILEBUF_FLAGS; + + _IO_link_in(fp); + fp->_fileno = -1; +} + +int +DEFUN(_IO_file_close_it, (fp), + register _IO_FILE* fp) +{ + int sync_status, close_status; + if (!_IO_file_is_open(fp)) + return EOF; + + sync_status = _IO_file_sync (fp); + + _IO_unsave_markers(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); + + _IO_un_link(fp); + fp->_flags = _IO_MAGIC|CLOSED_FILEBUF_FLAGS; + fp->_fileno = EOF; + fp->_offset = _IO_pos_BAD; + + return close_status ? close_status : sync_status; +} + +void +DEFUN(_IO_file_finish, (fp), + register _IO_FILE* fp) +{ + if (_IO_file_is_open(fp)) + { + _IO_do_flush (fp); + if (!(fp->_flags & _IO_DELETE_DONT_CLOSE)) + _IO_SYSCLOSE (fp); + } + _IO_default_finish(fp); +} + +_IO_FILE * +DEFUN(_IO_file_fopen, (fp, filename, mode), + register _IO_FILE *fp AND const char *filename AND const char *mode) +{ + int oflags = 0, omode; + int read_write, fdesc; + int oprot = 0666; + if (_IO_file_is_open (fp)) + return 0; + switch (*mode++) { + case 'r': + omode = O_RDONLY; + read_write = _IO_NO_WRITES; + break; + case 'w': + omode = O_WRONLY; + oflags = O_CREAT|O_TRUNC; + read_write = _IO_NO_READS; + break; + case 'a': + omode = O_WRONLY; + oflags = O_CREAT|O_APPEND; + read_write = _IO_NO_READS|_IO_IS_APPENDING; + break; + default: + errno = EINVAL; + return NULL; + } + if (mode[0] == '+' || (mode[0] == 'b' && mode[1] == '+')) { + omode = O_RDWR; + read_write &= _IO_IS_APPENDING; + } + fdesc = open(filename, omode|oflags, oprot); + if (fdesc < 0) + return NULL; + fp->_fileno = fdesc; + _IO_mask_flags(fp, read_write,_IO_NO_READS+_IO_NO_WRITES+_IO_IS_APPENDING); + if (read_write & _IO_IS_APPENDING) + if (_IO_SEEKOFF (fp, (_IO_off_t)0, _IO_seek_end, _IOS_INPUT|_IOS_OUTPUT) + == _IO_pos_BAD) + return NULL; + _IO_link_in(fp); + return fp; +} + +_IO_FILE* +DEFUN(_IO_file_attach, (fp, fd), + _IO_FILE *fp AND int fd) +{ + if (_IO_file_is_open(fp)) + return NULL; + fp->_fileno = fd; + fp->_flags &= ~(_IO_NO_READS+_IO_NO_WRITES); + fp->_flags |= _IO_DELETE_DONT_CLOSE; + fp->_offset = _IO_pos_BAD; + return fp; +} + +_IO_FILE* +DEFUN(_IO_file_setbuf, (fp, p, len), + register _IO_FILE *fp AND char* p AND _IO_ssize_t len) +{ + 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); + + return fp; +} + +/* Write TO_DO bytes from DATA to FP. + Then mark FP has having empty buffers. */ + +int +DEFUN(_IO_do_write, (fp, data, to_do), + register _IO_FILE *fp AND const char* data AND _IO_size_t to_do) +{ + _IO_size_t count; + if (to_do == 0) + return 0; + if (fp->_flags & _IO_IS_APPENDING) + /* On a system without a proper O_APPEND implementation, + you would need to sys_seek(0, SEEK_END) here, but is + is not needed nor desirable for Unix- or Posix-like systems. + Instead, just indicate that offset (before and after) is + unpredictable. */ + fp->_offset = _IO_pos_BAD; + else if (fp->_IO_read_end != fp->_IO_write_base) + { + _IO_pos_t new_pos + = _IO_SYSSEEK(fp, fp->_IO_write_base - fp->_IO_read_end, 1); + if (new_pos == _IO_pos_BAD) + return EOF; + fp->_offset = new_pos; + } + count = _IO_SYSWRITE (fp, data, to_do); + if (fp->_cur_column) + fp->_cur_column = _IO_adjust_column(fp->_cur_column - 1, data, to_do) + 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_buf_base + : fp->_IO_buf_end; + return count != to_do ? EOF : 0; +} + +int +DEFUN(_IO_file_underflow, (fp), + register _IO_FILE *fp) +{ + _IO_ssize_t count; +#if 0 + /* SysV does not make this test; take it out for compatibility */ + if (fp->_flags & _IO_EOF_SEEN) + return (EOF); +#endif + + if (fp->_flags & _IO_NO_READS) + return EOF; + if (fp->_IO_read_ptr < fp->_IO_read_end) + return *(unsigned char*)fp->_IO_read_ptr; + + if (fp->_IO_buf_base == NULL) + _IO_doallocbuf(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); + + count = _IO_SYSREAD (fp, fp->_IO_buf_base, + fp->_IO_buf_end - fp->_IO_buf_base); + if (count <= 0) + { + if (count == 0) + fp->_flags |= _IO_EOF_SEEN; + else + fp->_flags |= _IO_ERR_SEEN, count = 0; + } + fp->_IO_read_base = fp->_IO_read_ptr = fp->_IO_buf_base; + fp->_IO_read_end = fp->_IO_buf_base + count; + fp->_IO_write_base = fp->_IO_write_ptr = fp->_IO_write_end + = fp->_IO_buf_base; + if (count == 0) + return EOF; + if (fp->_offset != _IO_pos_BAD) + _IO_pos_adjust(fp->_offset, count); + return *(unsigned char*)fp->_IO_read_ptr; +} + +int +DEFUN(_IO_file_overflow, (f, ch), + register _IO_FILE* f AND int ch) +{ + if (f->_flags & _IO_NO_WRITES) /* SET ERROR */ + return EOF; + /* If currently reading or no buffer allocated. */ + if ((f->_flags & _IO_CURRENTLY_PUTTING) == 0) + { + /* Allocate a buffer if needed. */ + if (f->_IO_write_base == 0) + { + _IO_doallocbuf(f); + _IO_setg (f, f->_IO_buf_base, f->_IO_buf_base, f->_IO_buf_base); + } + /* Otherwise must be currently reading. */ + f->_IO_write_ptr = f->_IO_read_ptr; + f->_IO_write_base = f->_IO_write_ptr; + f->_IO_write_end = f->_IO_buf_end; + f->_IO_read_base = f->_IO_read_ptr = f->_IO_read_end; + + if (f->_flags & (_IO_LINE_BUF+_IO_UNBUFFERED)) + f->_IO_write_end = f->_IO_write_ptr; + f->_flags |= _IO_CURRENTLY_PUTTING; + } + if (ch == EOF) + return _IO_do_flush(f); + 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) + return EOF; + return (unsigned char)ch; +} + +int +DEFUN(_IO_file_sync, (fp), + register _IO_FILE* fp) +{ + _IO_size_t delta; + /* char* ptr = cur_ptr(); */ + if (fp->_IO_write_ptr > fp->_IO_write_base) + if (_IO_do_flush(fp)) return EOF; + delta = fp->_IO_read_ptr - fp->_IO_read_end; + if (delta != 0) + { +#ifdef TODO + if (_IO_in_backup(fp)) + delta -= eGptr() - Gbase(); +#endif + _IO_off_t new_pos = _IO_SYSSEEK (fp, delta, 1); + if (new_pos != (_IO_off_t)EOF) + fp->_IO_read_end = fp->_IO_read_ptr; +#ifdef ESPIPE + else if (errno == ESPIPE) + ; /* Ignore error from unseekable devices. */ +#endif + else + return EOF; + } + fp->_offset = _IO_pos_BAD; + /* FIXME: Cleanup - can this be shared? */ + /* setg(base(), ptr, ptr); */ + return 0; +} + +_IO_pos_t +DEFUN(_IO_file_seekoff, (fp, offset, dir, mode), + register _IO_FILE *fp AND _IO_off_t offset AND int dir AND int mode) +{ + _IO_pos_t result; + _IO_off_t delta, new_offset; + long count; + + 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->_IO_write_ptr > fp->_IO_write_base || _IO_in_put_mode(fp)) + if (_IO_switch_to_get_mode(fp)) return EOF; + + if (fp->_IO_buf_base == NULL) + { + _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); + } + + switch (dir) + { + case _IO_seek_cur: + /* Adjust for read-ahead (bytes is buffer). */ + offset -= fp->_IO_read_end - fp->_IO_read_ptr; + if (fp->_offset == _IO_pos_BAD) + goto dumb; + /* Make offset absolute, assuming current pointer is file_ptr(). */ + offset += _IO_pos_as_off(fp->_offset); + + dir = _IO_seek_set; + break; + case _IO_seek_set: + break; + case _IO_seek_end: + { + struct stat 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 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_pos_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) + { + _IO_setg(fp, fp->_IO_buf_base, fp->_IO_buf_base + rel_offset, + fp->_IO_read_end); + _IO_setp(fp, fp->_IO_buf_base, fp->_IO_buf_base); + return offset; + } +#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; + return offset; + } +#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); + return offset; + } +#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, + 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; +} + +_IO_ssize_t +DEFUN(_IO_file_read, (fp, buf, size), + register _IO_FILE* fp AND void* buf AND _IO_ssize_t size) +{ + for (;;) + { + _IO_ssize_t count = _IO_read(fp->_fileno, buf, size); +#ifdef EINTR + if (count == -1 && errno == EINTR) + continue; +#endif + return count; + } +} + +_IO_pos_t +DEFUN(_IO_file_seek, (fp, offset, dir), + _IO_FILE *fp AND _IO_off_t offset AND int dir) +{ + return _IO_lseek(fp->_fileno, offset, dir); +} + +int +DEFUN(_IO_file_stat, (fp, st), + _IO_FILE *fp AND void* st) +{ + return _IO_fstat(fp->_fileno, (struct stat*)st); +} + +int +DEFUN(_IO_file_close, (fp), + _IO_FILE* fp) +{ + return _IO_close(fp->_fileno); +} + +_IO_ssize_t +DEFUN(_IO_file_write, (f, data, n), + register _IO_FILE* f AND const void* data AND _IO_ssize_t n) +{ + _IO_ssize_t to_do = n; + while (to_do > 0) + { + _IO_ssize_t count = _IO_write(f->_fileno, data, to_do); + if (count == EOF) + { +#ifdef EINTR + if (errno == EINTR) + continue; + else +#endif + { + f->_flags |= _IO_ERR_SEEN; + break; + } + } + to_do -= count; + data = (void*)((char*)data + count); + } + n -= to_do; + if (f->_offset >= 0) + f->_offset += n; + return n; +} + +_IO_size_t +DEFUN(_IO_file_xsputn, (f, data, n), + _IO_FILE *f AND const void *data AND _IO_size_t n) +{ + register const char *s = (char*) 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->_IO_write_end - f->_IO_write_ptr; /* Space available. */ + if ((f->_flags & _IO_LINE_BUF) && (f->_flags & _IO_CURRENTLY_PUTTING)) + { + count = f->_IO_buf_end - f->_IO_write_ptr; + if (count >= n) + { register const char *p; + for (p = s + n; p > s; ) + { + if (*--p == '\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) { + memcpy(f->_IO_write_ptr, s, count); + s += count; + } + else + { + register char *p = f->_IO_write_ptr; + register int i = (int)count; + while (--i >= 0) *p++ = *s++; + } + f->_IO_write_ptr += count; + to_do -= count; + } + if (to_do + must_flush > 0) + { _IO_size_t block_size, dont_write; + /* Next flush the (full) buffer. */ + if (__overflow(f, EOF) == EOF) + return n - to_do; + + /* Try to maintain alignment: write a whole number of blocks. + dont_write is what gets left over. */ + block_size = f->_IO_buf_end - f->_IO_buf_base; + dont_write = block_size >= 128 ? to_do % block_size : 0; + + count = to_do - dont_write; + if (_IO_do_write(f, s, count) == EOF) + return n - to_do; + to_do = dont_write; + + /* Now write out the remainder. Normally, this will fit in the + buffer, but it's somewhat messier for line-buffered files, + so we let _IO_default_xsputn handle the general case. */ + if (dont_write) + to_do -= _IO_default_xsputn(f, s+count, dont_write); + } + return n - to_do; +} + +#if 0 +/* Work in progress */ +_IO_size_t +DEFUN(_IO_file_xsgetn, (fp, data, n), + _IO_FILE *fp AND void *data AND _IO_size_t n) +{ + register _IO_size_t more = n; + register char *s = data; + for (;;) + { + _IO_ssize_t count = fp->_IO_read_end - fp->_IO_read_ptr; /* Data available. */ + if (count > 0) + { + if (count > more) + count = more; + if (count > 20) + { + memcpy(s, fp->_IO_read_ptr, count); + s += count; + fp->_IO_read_ptr += count; + } + else if (count <= 0) + count = 0; + else + { + register char *p = fp->_IO_read_ptr; + register int i = (int)count; + while (--i >= 0) *s++ = *p++; + fp->_IO_read_ptr = p; + } + more -= count; + } +#if 0 + if (! _IO_in put_mode (fp) + && ! _IO_have_markers (fp) && ! IO_have_backup (fp)) + { + /* This is an optimization of _IO_file_underflow */ + if (fp->_flags & _IO_NO_READS) + break; + /* If we're reading a lot of data, don't bother allocating + a buffer. But if we're only reading a bit, perhaps we should ??*/ + if (count <= 512 && fp->_IO_buf_base == NULL) + _IO_doallocbuf(fp); + if (fp->_flags & (_IO_LINE_BUF|_IO_UNBUFFERED)) + _IO_flush_all_linebuffered(); + + _IO_switch_to_get_mode(fp); ???; + count = _IO_SYSREAD (fp, s, more); + if (count <= 0) + { + if (count == 0) + fp->_flags |= _IO_EOF_SEEN; + else + fp->_flags |= _IO_ERR_SEEN, count = 0; + } + + s += count; + more -= count; + } +#endif + if (more == 0 || __underflow(fp) == EOF) + break; + } + return n - more; +} +#endif + +struct _IO_jump_t _IO_file_jumps = { + JUMP_INIT_DUMMY, + JUMP_INIT(finish, _IO_file_finish), + JUMP_INIT(overflow, _IO_file_overflow), + JUMP_INIT(underflow, _IO_file_underflow), + JUMP_INIT(uflow, _IO_default_uflow), + JUMP_INIT(pbackfail, _IO_default_pbackfail), + JUMP_INIT(xsputn, _IO_file_xsputn), + JUMP_INIT(xsgetn, _IO_default_xsgetn), + JUMP_INIT(seekoff, _IO_file_seekoff), + JUMP_INIT(seekpos, _IO_default_seekpos), + JUMP_INIT(setbuf, _IO_file_setbuf), + JUMP_INIT(sync, _IO_file_sync), + JUMP_INIT(doallocate, _IO_file_doallocate), + JUMP_INIT(read, _IO_file_read), + JUMP_INIT(write, _IO_file_write), + JUMP_INIT(seek, _IO_file_seek), + JUMP_INIT(close, _IO_file_close), + JUMP_INIT(stat, _IO_file_stat) +}; diff --git a/libio/fputc.c b/libio/fputc.c new file mode 100644 index 0000000000..2339139f72 --- /dev/null +++ b/libio/fputc.c @@ -0,0 +1,35 @@ +/* +Copyright (C) 1993 Free Software Foundation + +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" + +int +fputc (c, fp) + int c; + _IO_FILE *fp; +{ + CHECK_FILE (fp, EOF); + return _IO_putc (c, fp); +} diff --git a/libio/freopen.c b/libio/freopen.c new file mode 100644 index 0000000000..22fa13a697 --- /dev/null +++ b/libio/freopen.c @@ -0,0 +1,38 @@ +/* +Copyright (C) 1993, 1995 Free Software Foundation + +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" + +FILE* +freopen (filename, mode, fp) + const char* filename; + const char* mode; + FILE* fp; +{ + CHECK_FILE (fp, NULL); + if (!(fp->_flags & _IO_IS_FILEBUF)) + return NULL; + return _IO_freopen (filename, mode, fp); +} diff --git a/libio/fseek.c b/libio/fseek.c new file mode 100644 index 0000000000..3afc4283e6 --- /dev/null +++ b/libio/fseek.c @@ -0,0 +1,36 @@ +/* +Copyright (C) 1993, 1995 Free Software Foundation + +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 "stdio.h" +#include "libioP.h" + +int +fseek (fp, offset, whence) + _IO_FILE* fp; + long int offset; + int whence; +{ + CHECK_FILE (fp, -1); + return _IO_fseek (fp, offset, whence); +} diff --git a/libio/genops.c b/libio/genops.c new file mode 100644 index 0000000000..7eb2d43ee1 --- /dev/null +++ b/libio/genops.c @@ -0,0 +1,837 @@ +/* +Copyright (C) 1993, 1995 Free Software Foundation + +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. */ + +/* Generic or default I/O operations. */ + +#include "libioP.h" +#ifdef __STDC__ +#include <stdlib.h> +#endif +#include <string.h> + +void +DEFUN(_IO_un_link, (fp), + _IO_FILE *fp) +{ + if (fp->_flags & _IO_LINKED) { + _IO_FILE **f; + for (f = &_IO_list_all; *f != NULL; f = &(*f)->_chain) { + if (*f == fp) { + *f = fp->_chain; + break; + } + } + fp->_flags &= ~_IO_LINKED; + } +} + +void +DEFUN(_IO_link_in, (fp), + _IO_FILE *fp) +{ + if ((fp->_flags & _IO_LINKED) == 0) { + fp->_flags |= _IO_LINKED; + fp->_chain = _IO_list_all; + _IO_list_all = fp; + } +} + +/* Return minimum _pos markers + Assumes the current get area is the main get area. */ + +_IO_size_t +DEFUN(_IO_least_marker, (fp), + register _IO_FILE *fp) +{ + _IO_ssize_t least_so_far = fp->_IO_read_end - fp->_IO_read_base; + register 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 +DEFUN(_IO_switch_to_main_get_area, (fp), + _IO_FILE *fp) +{ + char *tmp; + fp->_flags &= ~_IO_IN_BACKUP; + /* Swap _IO_read_end and _IO_save_end. */ + tmp = fp->_IO_read_end; fp->_IO_read_end= fp->_IO_save_end; fp->_IO_save_end= tmp; + /* Swap _IO_read_base and _IO_save_base. */ + tmp = fp->_IO_read_base; fp->_IO_read_base = fp->_IO_save_base; fp->_IO_save_base = tmp; + fp->_IO_read_ptr = fp->_IO_read_base; +} + +/* Switch current get area from main get area to (end of) backup area. */ + +void +DEFUN(_IO_switch_to_backup_area, (fp), + register _IO_FILE *fp) +{ + char *tmp; + fp->_flags |= _IO_IN_BACKUP; + /* Swap _IO_read_end and _IO_save_end. */ + tmp = fp->_IO_read_end; fp->_IO_read_end = fp->_IO_save_end; fp->_IO_save_end = tmp; + /* Swap _gbase and _IO_save_base. */ + tmp = fp->_IO_read_base; fp->_IO_read_base = fp->_IO_save_base; fp->_IO_save_base = tmp; + fp->_IO_read_ptr = fp->_IO_read_end; +} + +int +DEFUN(_IO_switch_to_get_mode, (fp), + register _IO_FILE *fp) +{ + if (fp->_IO_write_ptr > fp->_IO_write_base) + if (_IO_OVERFLOW (fp, EOF) == EOF) + return EOF; + if (_IO_in_backup(fp)) + fp->_IO_read_base = fp->_IO_backup_base; + else + { + fp->_IO_read_base = fp->_IO_buf_base; + if (fp->_IO_write_ptr > fp->_IO_read_end) + fp->_IO_read_end = fp->_IO_write_ptr; + } + fp->_IO_read_ptr = fp->_IO_write_ptr; + + fp->_IO_write_base = fp->_IO_write_ptr = fp->_IO_write_end = fp->_IO_read_ptr; + + fp->_flags &= ~_IO_CURRENTLY_PUTTING; + return 0; +} + +void +DEFUN(_IO_free_backup_area, (fp), + register _IO_FILE *fp) +{ + if (_IO_in_backup (fp)) + _IO_switch_to_main_get_area(fp); /* Just in case. */ + free (fp->_IO_save_base); + fp->_IO_save_base = NULL; + fp->_IO_save_end = NULL; + fp->_IO_backup_base = NULL; +} + +#if 0 +int +DEFUN(_IO_switch_to_put_mode, (fp), + register _IO_FILE *fp) +{ + fp->_IO_write_base = fp->_IO_read_ptr; + fp->_IO_write_ptr = fp->_IO_read_ptr; + /* Following is wrong if line- or un-buffered? */ + fp->_IO_write_end = fp->_flags & _IO_IN_BACKUP ? fp->_IO_read_end : fp->_IO_buf_end; + + fp->_IO_read_ptr = fp->_IO_read_end; + fp->_IO_read_base = fp->_IO_read_end; + + fp->_flags |= _IO_CURRENTLY_PUTTING; + return 0; +} +#endif + +int +DEFUN(__overflow, (f, ch), + _IO_FILE *f AND int ch) +{ + return _IO_OVERFLOW (f, ch); +} + +static int +DEFUN(save_for_backup, (fp), + _IO_FILE *fp) +{ + /* Append [_IO_read_base.._IO_read_end] to backup area. */ + int least_mark = _IO_least_marker(fp); + /* needed_size is how much space we need in the backup area. */ + int needed_size = (fp->_IO_read_end - fp->_IO_read_base) - least_mark; + int current_Bsize = fp->_IO_save_end - fp->_IO_save_base; + int avail; /* Extra space available for future expansion. */ + int delta; + struct _IO_marker *mark; + if (needed_size > current_Bsize) + { + char *new_buffer; + avail = 100; + new_buffer = (char*)malloc(avail+needed_size); + if (new_buffer == NULL) + return EOF; /* FIXME */ + if (least_mark < 0) + { + memcpy(new_buffer + avail, + fp->_IO_save_end + least_mark, + -least_mark); + memcpy(new_buffer +avail - least_mark, + fp->_IO_read_base, + fp->_IO_read_end - fp->_IO_read_base); + } + else + memcpy(new_buffer + avail, + fp->_IO_read_base + least_mark, + needed_size); + if (fp->_IO_save_base) + free (fp->_IO_save_base); + fp->_IO_save_base = new_buffer; + fp->_IO_save_end = new_buffer + avail + needed_size; + } + else + { + avail = current_Bsize - needed_size; + if (least_mark < 0) + { + memmove(fp->_IO_save_base + avail, + fp->_IO_save_end + least_mark, + -least_mark); + memcpy(fp->_IO_save_base + avail - least_mark, + fp->_IO_read_base, + fp->_IO_read_end - fp->_IO_read_base); + } + else if (needed_size > 0) + memcpy(fp->_IO_save_base + avail, + fp->_IO_read_base + least_mark, + needed_size); + } + /* FIXME: Dubious arithmetic if pointers are NULL */ + fp->_IO_backup_base = fp->_IO_save_base + avail; + /* Adjust all the streammarkers. */ + delta = fp->_IO_read_end - fp->_IO_read_base; + for (mark = fp->_markers; mark != NULL; mark = mark->_next) + mark->_pos -= delta; + return 0; +} + +int +DEFUN(__underflow, (fp), + _IO_FILE *fp) +{ + if (_IO_in_put_mode(fp)) + if (_IO_switch_to_get_mode(fp) == EOF) return EOF; + if (fp->_IO_read_ptr < fp->_IO_read_end) + return *(unsigned char*)fp->_IO_read_ptr; + if (_IO_in_backup(fp)) + { + _IO_switch_to_main_get_area(fp); + if (fp->_IO_read_ptr < fp->_IO_read_end) + return *fp->_IO_read_ptr; + } + if (_IO_have_markers(fp)) + { + if (save_for_backup (fp)) + return EOF; + } + else if (_IO_have_backup(fp)) + _IO_free_backup_area(fp); + return _IO_UNDERFLOW (fp); +} + +int +DEFUN(__uflow, (fp), + _IO_FILE *fp) +{ + if (_IO_in_put_mode(fp)) + if (_IO_switch_to_get_mode(fp) == EOF) return EOF; + if (fp->_IO_read_ptr < fp->_IO_read_end) + return *(unsigned char*)fp->_IO_read_ptr++; + if (_IO_in_backup(fp)) + { + _IO_switch_to_main_get_area(fp); + if (fp->_IO_read_ptr < fp->_IO_read_end) + return *fp->_IO_read_ptr++; + } + if (_IO_have_markers(fp)) + { + if (save_for_backup (fp)) + return EOF; + } + else if (_IO_have_backup(fp)) + _IO_free_backup_area(fp); + return _IO_UFLOW (fp); +} + +void +DEFUN(_IO_setb, (f, b, eb, a), + _IO_FILE *f AND char *b AND char *eb AND int a) +{ + if (f->_IO_buf_base && !(f->_flags & _IO_USER_BUF)) + FREE_BUF(f->_IO_buf_base); + f->_IO_buf_base = b; + f->_IO_buf_end = eb; + if (a) + f->_flags &= ~_IO_USER_BUF; + else + f->_flags |= _IO_USER_BUF; +} + +void +DEFUN(_IO_doallocbuf, (fp), + register _IO_FILE *fp) +{ + if (fp->_IO_buf_base) + return; + if (!(fp->_flags & _IO_UNBUFFERED)) + if (_IO_DOALLOCATE (fp) != EOF) + return; + _IO_setb(fp, fp->_shortbuf, fp->_shortbuf+1, 0); +} + +int +DEFUN(_IO_default_underflow, (fp), + _IO_FILE *fp) +{ + return EOF; +} + +int +DEFUN(_IO_default_uflow, (fp), + _IO_FILE *fp) +{ + int ch = _IO_UNDERFLOW (fp); + if (ch == EOF) + return EOF; + return *(unsigned char*)fp->_IO_read_ptr++; +} + +_IO_size_t +DEFUN(_IO_default_xsputn, (f, data, n), + register _IO_FILE *f AND const void *data AND _IO_size_t n) +{ + register const char *s = (char*) data; + register _IO_size_t more = n; + if (more <= 0) + return 0; + for (;;) + { + _IO_ssize_t count = f->_IO_write_end - f->_IO_write_ptr; /* Space available. */ + if (count > 0) + { + if (count > more) + count = more; + if (count > 20) + { + memcpy(f->_IO_write_ptr, s, count); + s += count; + f->_IO_write_ptr += count; + } + else if (count <= 0) + count = 0; + else + { + register char *p = f->_IO_write_ptr; + register _IO_ssize_t i; + for (i = count; --i >= 0; ) *p++ = *s++; + f->_IO_write_ptr = p; + } + more -= count; + } + if (more == 0 || __overflow(f, (unsigned char)*s++) == EOF) + break; + more--; + } + return n - more; +} + +_IO_size_t +DEFUN(_IO_sgetn, (fp, data, n), + _IO_FILE *fp AND void *data AND _IO_size_t n) +{ + /* FIXME handle putback buffer here! */ + return _IO_XSGETN (fp, data, n); +} + +_IO_size_t +DEFUN(_IO_default_xsgetn, (fp, data, n), + _IO_FILE *fp AND void *data AND _IO_size_t n) +{ + register _IO_size_t more = n; + register char *s = (char*) data; + for (;;) + { + _IO_ssize_t count = fp->_IO_read_end - fp->_IO_read_ptr; /* Data available. */ + if (count > 0) + { + if (count > more) + count = more; + if (count > 20) + { + memcpy(s, fp->_IO_read_ptr, count); + s += count; + fp->_IO_read_ptr += count; + } + else if (count <= 0) + count = 0; + else + { + register char *p = fp->_IO_read_ptr; + register int i = (int)count; + while (--i >= 0) *s++ = *p++; + fp->_IO_read_ptr = p; + } + more -= count; + } + if (more == 0 || __underflow(fp) == EOF) + break; + } + return n - more; +} + +int +DEFUN(_IO_sync, (fp), + register _IO_FILE *fp) +{ + return 0; +} + +_IO_FILE* +DEFUN(_IO_default_setbuf, (fp, p, len), + register _IO_FILE *fp AND char* p AND _IO_ssize_t len) +{ + if (_IO_SYNC (fp) == EOF) + return NULL; + if (p == NULL || len == 0) + { + fp->_flags |= _IO_UNBUFFERED; + _IO_setb(fp, fp->_shortbuf, fp->_shortbuf+1, 0); + } + else + { + fp->_flags &= ~_IO_UNBUFFERED; + _IO_setb(fp, p, p+len, 0); + } + fp->_IO_write_base = fp->_IO_write_ptr = fp->_IO_write_end = 0; + fp->_IO_read_base = fp->_IO_read_ptr = fp->_IO_read_end = 0; + return fp; +} + +_IO_pos_t +DEFUN(_IO_default_seekpos, (fp, pos, mode), + _IO_FILE *fp AND _IO_pos_t pos AND int mode) +{ + return _IO_SEEKOFF (fp, _IO_pos_as_off(pos), 0, mode); +} + +int +DEFUN(_IO_default_doallocate, (fp), + _IO_FILE *fp) +{ + char *buf = ALLOC_BUF(_IO_BUFSIZ); + if (buf == NULL) + return EOF; + _IO_setb(fp, buf, buf+_IO_BUFSIZ, 1); + return 1; +} + +void +DEFUN(_IO_init, (fp, flags), + register _IO_FILE *fp AND int flags) +{ + fp->_flags = _IO_MAGIC|flags; + fp->_IO_buf_base = NULL; + fp->_IO_buf_end = NULL; + fp->_IO_read_base = NULL; + fp->_IO_read_ptr = NULL; + fp->_IO_read_end = NULL; + fp->_IO_write_base = NULL; + fp->_IO_write_ptr = NULL; + fp->_IO_write_end = NULL; + fp->_chain = NULL; /* Not necessary. */ + + fp->_IO_save_base = NULL; + fp->_IO_backup_base = NULL; + fp->_IO_save_end = NULL; + fp->_markers = NULL; + fp->_cur_column = 0; +} + +int +DEFUN(_IO_default_sync, (fp), + _IO_FILE *fp) +{ + return 0; +} + +/* The way the C++ classes are mapped into the C functions in the + current implementation, this function can get called twice! */ + +void +DEFUN(_IO_default_finish, (fp), + _IO_FILE *fp) +{ + struct _IO_marker *mark; + if (fp->_IO_buf_base && !(fp->_flags & _IO_USER_BUF)) + { + FREE_BUF(fp->_IO_buf_base); + fp->_IO_buf_base = fp->_IO_buf_end = NULL; + } + + for (mark = fp->_markers; mark != NULL; mark = mark->_next) + mark->_sbuf = NULL; + + if (fp->_IO_save_base) + { + free (fp->_IO_save_base); + fp->_IO_save_base = NULL; + } + + _IO_un_link(fp); +} + +_IO_pos_t +DEFUN(_IO_default_seekoff, (fp, offset, dir, mode), + register _IO_FILE *fp AND _IO_off_t offset AND int dir AND int mode) +{ + return _IO_pos_BAD; +} + +int +DEFUN(_IO_sputbackc, (fp, c), + register _IO_FILE *fp AND int c) +{ + if (fp->_IO_read_ptr > fp->_IO_read_base + && (unsigned char)fp->_IO_read_ptr[-1] == (unsigned char)c) + { + fp->_IO_read_ptr--; + return (unsigned char)c; + } + return _IO_PBACKFAIL (fp, c); +} + +int +DEFUN(_IO_sungetc, (fp), + register _IO_FILE *fp) +{ + if (fp->_IO_read_ptr > fp->_IO_read_base) + { + fp->_IO_read_ptr--; + return (unsigned char)*fp->_IO_read_ptr; + } + else + return _IO_PBACKFAIL (fp, EOF); +} + +#if 0 /* Work in progress */ +void +DEFUN(_IO_set_column, (fp, c), + register _IO_FILE *fp AND int c) +{ + if (c == -1) + fp->_column = -1; + else + fp->_column = c - (fp->_IO_write_ptr - fp->_IO_write_base); +} +#else +int +DEFUN(_IO_set_column, (fp, i), + register _IO_FILE *fp AND int i) +{ + fp->_cur_column = i+1; + return 0; +} +#endif + + +unsigned +DEFUN(_IO_adjust_column, (start, line, count), + unsigned start AND const char *line AND int count) +{ + register const char *ptr = line + count; + while (ptr > line) + if (*--ptr == '\n') + return line + count - ptr - 1; + return start + count; +} + +int +DEFUN(_IO_get_column, (fp), + register _IO_FILE *fp) +{ + if (fp->_cur_column) + return _IO_adjust_column(fp->_cur_column - 1, + fp->_IO_write_base, + fp->_IO_write_ptr - fp->_IO_write_base); + return -1; +} + +int +DEFUN_VOID(_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 + && _IO_OVERFLOW (fp, EOF) == EOF) + result = EOF; + return result; +} + +void +DEFUN_VOID(_IO_flush_all_linebuffered) +{ + _IO_FILE *fp; + for (fp = _IO_list_all; fp != NULL; fp = fp->_chain) + if (fp->_flags & _IO_LINE_BUF) + _IO_OVERFLOW (fp, EOF); +} + +void +DEFUN_VOID(_IO_unbuffer_all) +{ + _IO_FILE *fp; + for (fp = _IO_list_all; fp != NULL; fp = fp->_chain) + if (! (fp->_flags & _IO_UNBUFFERED)) + _IO_SETBUF (fp, NULL, 0); +} + +void +DEFUN_VOID(_IO_cleanup) +{ + _IO_flush_all (); + + /* We currently don't have a reliable mechanism for making sure that + C++ static destructors are executed in the correct order. + So it is possible that other static destructord might want to + write to cout - and they're supposed to be able to do so. + + The following will make the standard streambufs be unbuffered, + which forces any output from late destructors to be written out. */ + _IO_unbuffer_all (); +} + +void +DEFUN(_IO_init_marker, (marker, fp), + struct _IO_marker *marker AND _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->_IO_read_ptr - fp->_IO_read_end; + else + marker->_pos = fp->_IO_read_ptr - fp->_IO_read_base; + + /* Should perhaps sort the chain? */ + marker->_next = fp->_markers; + fp->_markers = marker; +} + +void +DEFUN(_IO_remove_marker, (marker), + register struct _IO_marker *marker) +{ + /* Unlink from sb's chain. */ + register struct _IO_marker **ptr = &marker->_sbuf->_markers; + for (; ; ptr = &(*ptr)->_next) + { + if (*ptr == NULL) + break; + else if (*ptr == marker) + { + *ptr = marker->_next; + return; + } + } +#if 0 + if _sbuf has a backup area that is no longer needed, should we delete + it now, or wait until the next underflow? +#endif +} + +#define BAD_DELTA EOF + +int +DEFUN(_IO_marker_difference, (mark1, mark2), + struct _IO_marker *mark1 AND struct _IO_marker *mark2) +{ + return mark1->_pos - mark2->_pos; +} + +/* Return difference between MARK and current posistion of MARK's stream. */ +int +DEFUN(_IO_marker_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->_IO_read_ptr - mark->_sbuf->_IO_read_end; + else + cur_pos = mark->_sbuf->_IO_read_ptr - mark->_sbuf->_IO_read_base; + return mark->_pos - cur_pos; +} + +int +DEFUN(_IO_seekmark, (fp, mark, delta), + _IO_FILE *fp AND struct _IO_marker *mark AND int delta) +{ + if (mark->_sbuf != fp) + return EOF; + if (mark->_pos >= 0) + { + if (_IO_in_backup(fp)) + _IO_switch_to_main_get_area(fp); + fp->_IO_read_ptr = fp->_IO_read_base + mark->_pos; + } + else + { + if (!_IO_in_backup(fp)) + _IO_switch_to_backup_area(fp); + fp->_IO_read_ptr = fp->_IO_read_end + mark->_pos; + } + return 0; +} + +void +DEFUN(_IO_unsave_markers, (fp), + register _IO_FILE *fp) +{ + register 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_backup_area(fp); +} + +int +DEFUN(_IO_nobackup_pbackfail, (fp, c), + register _IO_FILE *fp AND int c) +{ + if (fp->_IO_read_ptr > fp->_IO_read_base) + fp->_IO_read_ptr--; + if (c != EOF && *fp->_IO_read_ptr != c) + *fp->_IO_read_ptr = c; + return (unsigned char)c; +} + +int +DEFUN(_IO_default_pbackfail, (fp, c), + register _IO_FILE *fp AND int c) +{ + if (fp->_IO_read_ptr <= fp->_IO_read_base) + { + /* Need to handle a filebuf in write mode (switch to read mode). FIXME!*/ + if (_IO_have_backup(fp) && !_IO_in_backup(fp)) + _IO_switch_to_backup_area(fp); + + if (!_IO_have_backup(fp)) + { + /* No backup buffer: allocate one. */ + /* Use nshort buffer, if unused? (probably not) FIXME */ + int backup_size = 128; + char *bbuf = (char*)malloc(backup_size); + if (bbuf == NULL) + return EOF; + fp->_IO_save_base = bbuf; + fp->_IO_save_end = fp->_IO_save_base + backup_size; + fp->_IO_backup_base = fp->_IO_save_end; + _IO_switch_to_backup_area(fp); + } + else if (fp->_IO_read_ptr <= fp->_IO_read_base) + { + /* Increase size of existing backup buffer. */ + _IO_size_t new_size; + _IO_size_t old_size = fp->_IO_read_end - fp->_IO_read_base; + char *new_buf; + new_size = 2 * old_size; + new_buf = (char*)malloc(new_size); + if (new_buf == NULL) + return EOF; + memcpy(new_buf+(new_size-old_size), fp->_IO_read_base, old_size); + free (fp->_IO_read_base); + _IO_setg(fp, + new_buf, new_buf+(new_size-old_size), new_buf+new_size); + fp->_IO_backup_base = fp->_IO_read_ptr; + } + } + fp->_IO_read_ptr--; + if (c != EOF && *fp->_IO_read_ptr != c) + *fp->_IO_read_ptr = c; + return (unsigned char)*fp->_IO_read_ptr; +} + +_IO_pos_t +DEFUN(_IO_default_seek, (fp, offset, dir), + _IO_FILE *fp AND _IO_off_t offset AND int dir) +{ + return _IO_pos_BAD; +} + +int +DEFUN(_IO_default_stat, (fp, st), + _IO_FILE *fp AND void* st) +{ + return EOF; +} + +_IO_ssize_t +DEFUN(_IO_default_read, (fp, data, n), + register _IO_FILE* fp AND void* data AND _IO_ssize_t n) +{ + return -1; +} + +_IO_ssize_t +DEFUN(_IO_default_write, (fp, data, n), + register _IO_FILE* fp AND const void* data AND _IO_ssize_t n) +{ + return 0; +} + + +#ifdef TODO +#if defined(linux) +#define IO_CLEANUP ; +#endif + +#ifdef IO_CLEANUP + IO_CLEANUP +#else +struct __io_defs { + __io_defs() { } + ~__io_defs() { _IO_cleanup(); } +}; +__io_defs io_defs__; +#endif + +#endif /* TODO */ diff --git a/libio/getc.c b/libio/getc.c new file mode 100644 index 0000000000..844bca4750 --- /dev/null +++ b/libio/getc.c @@ -0,0 +1,35 @@ +/* +Copyright (C) 1993, 1995 Free Software Foundation + +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 getc + +int +getc (stream) + FILE *stream; +{ + return _IO_getc (stream); +} diff --git a/libio/getchar.c b/libio/getchar.c new file mode 100644 index 0000000000..875bceb83d --- /dev/null +++ b/libio/getchar.c @@ -0,0 +1,34 @@ +/* +Copyright (C) 1993 Free Software Foundation + +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 getchar + +int +getchar () +{ + return _IO_getc (stdin); +} diff --git a/libio/iofclose.c b/libio/iofclose.c new file mode 100644 index 0000000000..c797d86fd8 --- /dev/null +++ b/libio/iofclose.c @@ -0,0 +1,51 @@ +/* +Copyright (C) 1993, 1995 Free Software Foundation + +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 __STDC__ +#include <stdlib.h> +#endif + +int +_IO_fclose (fp) + register _IO_FILE *fp; +{ + int status; + + CHECK_FILE(fp, EOF); + + if (fp->_IO_file_flags & _IO_IS_FILEBUF) + status = _IO_file_close_it (fp); + else + status = fp->_flags & _IO_ERR_SEEN ? -1 : 0; + _IO_FINISH (fp); + if (fp != _IO_stdin && fp != _IO_stdout && fp != _IO_stderr) + { + fp->_IO_file_flags = 0; + free(fp); + } + return status; +} + +weak_alias (_IO_fclose, fclose) diff --git a/libio/iofdopen.c b/libio/iofdopen.c new file mode 100644 index 0000000000..6bb19fa214 --- /dev/null +++ b/libio/iofdopen.c @@ -0,0 +1,124 @@ +/* +Copyright (C) 1993, 1994 Free Software Foundation + +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. */ + +#ifdef __STDC__ +#include <stdlib.h> +#endif +#include "libioP.h" +#include <fcntl.h> + +#ifndef _IO_fcntl +#define _IO_fcntl fcntl +#endif + +_IO_FILE * +_IO_fdopen (fd, mode) + int fd; + const char *mode; +{ + int read_write; + int posix_mode = 0; + struct _IO_FILE_plus *fp; + int fd_flags; + + switch (*mode++) + { + case 'r': + read_write = _IO_NO_WRITES; + break; + case 'w': + read_write = _IO_NO_READS; + break; + case 'a': + posix_mode = O_APPEND; + read_write = _IO_NO_READS|_IO_IS_APPENDING; + break; + default: +#ifdef EINVAL + errno = EINVAL; +#endif + return NULL; + } + if (mode[0] == '+' || (mode[0] == 'b' && mode[1] == '+')) + read_write &= _IO_IS_APPENDING; +#ifdef F_GETFL + fd_flags = _IO_fcntl (fd, F_GETFL); +#ifndef O_ACCMODE +#define O_ACCMODE (O_RDONLY|O_WRONLY|O_RDWR) +#endif + if (fd_flags == -1 + || ((fd_flags & O_ACCMODE) == O_RDONLY && !(read_write & _IO_NO_WRITES)) + || ((fd_flags & O_ACCMODE) == O_WRONLY && !(read_write & _IO_NO_READS))) + return NULL; + + /* The May 93 draft of P1003.4/D14.1 (redesignated as 1003.1b) + [System Application Program Interface (API) Amendment 1: + Realtime Extensions], Rationale B.8.3.3 + Open a Stream on a File Descriptor says: + + Although not explicitly required by POSIX.1, a good + implementation of append ("a") mode would cause the + O_APPEND flag to be set. + + (Historical implementations [such as Solaris2] do a one-time + seek in fdopen.) + + However, we do not turn O_APPEND off if the mode is "w" (even + though that would seem consistent) because that would be more + likely to break historical programs. + */ + if ((posix_mode & O_APPEND) && !(fd_flags & O_APPEND)) + { +#ifdef F_SETFL + if (_IO_fcntl (fd, F_SETFL, fd_flags | O_APPEND) == -1) +#endif + return NULL; + } +#endif + + fp = (struct _IO_FILE_plus *) malloc (sizeof (struct _IO_FILE_plus)); + if (fp == NULL) + return NULL; + _IO_init (&fp->file, 0); + _IO_JUMPS (&fp->file) = &_IO_file_jumps; + _IO_file_init (&fp->file); +#if !_IO_UNIFIED_JUMPTABLES + fp->vtable = NULL; +#endif + if (_IO_file_attach (&fp->file, fd) == NULL) + { + _IO_un_link (&fp->file); + free (fp); + return NULL; + } + fp->file._flags &= ~_IO_DELETE_DONT_CLOSE; + + fp->file._IO_file_flags = + _IO_mask_flags (&fp->file, read_write, + _IO_NO_READS+_IO_NO_WRITES+_IO_IS_APPENDING); + + return (_IO_FILE *) fp; +} + +weak_alias (_IO_fdopen, fdopen) diff --git a/libio/iofflush.c b/libio/iofflush.c new file mode 100644 index 0000000000..1f549505c5 --- /dev/null +++ b/libio/iofflush.c @@ -0,0 +1,40 @@ +/* +Copyright (C) 1993, 1995 Free Software Foundation + +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" + +int +_IO_fflush (fp) + register _IO_FILE *fp; +{ + if (fp == NULL) + return _IO_flush_all (); + else + { + CHECK_FILE (fp, EOF); + return _IO_SYNC (fp) ? EOF : 0; + } +} + +weak_alias (_IO_fflush, fflush) diff --git a/libio/iofgetpos.c b/libio/iofgetpos.c new file mode 100644 index 0000000000..bc2215fc01 --- /dev/null +++ b/libio/iofgetpos.c @@ -0,0 +1,49 @@ +/* +Copyright (C) 1993, 1995 Free Software Foundation + +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> +/* ANSI explicily requires setting errno to a positive value on failure. */ + +int +_IO_fgetpos (fp, posp) + _IO_FILE* fp; + _IO_fpos_t *posp; +{ + _IO_fpos_t pos; + CHECK_FILE (fp, EOF); + pos = _IO_seekoff (fp, 0, _IO_seek_cur, 0); + if (pos == _IO_pos_BAD) + { +#ifdef EIO + if (errno == 0) + errno = EIO; +#endif + return EOF; + } + *posp = pos; + return 0; +} + +weak_alias (_IO_fgetpos, fgetpos) diff --git a/libio/iofgets.c b/libio/iofgets.c new file mode 100644 index 0000000000..a9f161dce8 --- /dev/null +++ b/libio/iofgets.c @@ -0,0 +1,44 @@ +/* +Copyright (C) 1993, 1995 Free Software Foundation + +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" + +char* +_IO_fgets (buf, n, fp) + char* buf; + int n; + _IO_FILE* fp; +{ + _IO_size_t count; + CHECK_FILE (fp, NULL); + if (n <= 0) + return NULL; + count = _IO_getline (fp, buf, n - 1, '\n', 1); + if (count == 0 || (fp->_IO_file_flags & _IO_ERR_SEEN)) + return NULL; + buf[count] = 0; + return buf; +} + +weak_alias (_IO_fgets, fgets) diff --git a/libio/iofopen.c b/libio/iofopen.c new file mode 100644 index 0000000000..14cce5336a --- /dev/null +++ b/libio/iofopen.c @@ -0,0 +1,52 @@ +/* +Copyright (C) 1993 Free Software Foundation + +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 __STDC__ +#include <stdlib.h> +#endif + +_IO_FILE * +_IO_fopen (filename, mode) + const char *filename; + const char *mode; +{ + struct _IO_FILE_plus *fp = + (struct _IO_FILE_plus *) malloc (sizeof (struct _IO_FILE_plus)); + if (fp == NULL) + return NULL; + _IO_init (&fp->file, 0); + _IO_JUMPS (&fp->file) = &_IO_file_jumps; + _IO_file_init (&fp->file); +#if !_IO_UNIFIED_JUMPTABLES + fp->vtable = NULL; +#endif + if (_IO_file_fopen (&fp->file, filename, mode) != NULL) + return (_IO_FILE *) fp; + _IO_un_link (&fp->file); + free (fp); + return NULL; +} + +weak_alias (_IO_fopen, fopen) diff --git a/libio/iofopncook.c b/libio/iofopncook.c new file mode 100644 index 0000000000..0b57ecd344 --- /dev/null +++ b/libio/iofopncook.c @@ -0,0 +1,163 @@ +/* +Copyright (C) 1993, 1995 Free Software Foundation + +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 <stdlib.h> + +struct _IO_cookie_file { + struct _IO_FILE file; + const void *vtable; + void *cookie; + _IO_cookie_io_functions_t io_functions; +}; + + +static _IO_ssize_t +_IO_cookie_read (fp, buf, size) + register _IO_FILE* fp; + void* buf; + _IO_ssize_t size; +{ + struct _IO_cookie_file *cfile = (struct _IO_cookie_file *) fp; + + if (cfile->io_functions.read == NULL) + return -1; + + return cfile->io_functions.read (cfile->cookie, buf, size); +} + +static _IO_ssize_t +_IO_cookie_write (fp, buf, size) + register _IO_FILE* fp; + const void* buf; + _IO_ssize_t size; +{ + struct _IO_cookie_file *cfile = (struct _IO_cookie_file *) fp; + + if (cfile->io_functions.write == NULL) + return -1; + + return cfile->io_functions.write (cfile->cookie, buf, size); +} + +static _IO_fpos_t +_IO_cookie_seek (fp, offset, dir) + _IO_FILE *fp; + _IO_off_t offset; + int dir; +{ + struct _IO_cookie_file *cfile = (struct _IO_cookie_file *) fp; + _IO_fpos_t pos; + + if (cfile->io_functions.seek == NULL) + return _IO_pos_BAD; + + pos = _IO_pos_0; + _IO_pos_adjust (pos, offset); + + if (cfile->io_functions.seek (cfile->cookie, pos, dir)) + return _IO_pos_BAD; + + return pos; +} + +static int +_IO_cookie_close (fp) + _IO_FILE* fp; +{ + struct _IO_cookie_file *cfile = (struct _IO_cookie_file *) fp; + + if (cfile->io_functions.close == NULL) + return 0; + + return cfile->io_functions.close (cfile->cookie); +} + + +static struct _IO_jump_t _IO_cookie_jumps = { + JUMP_INIT_DUMMY, + JUMP_INIT(finish, _IO_file_finish), + JUMP_INIT(overflow, _IO_file_overflow), + JUMP_INIT(underflow, _IO_file_underflow), + JUMP_INIT(uflow, _IO_default_uflow), + JUMP_INIT(pbackfail, _IO_default_pbackfail), + JUMP_INIT(xsputn, _IO_file_xsputn), + JUMP_INIT(xsgetn, _IO_default_xsgetn), + JUMP_INIT(seekoff, _IO_file_seekoff), + JUMP_INIT(seekpos, _IO_default_seekpos), + JUMP_INIT(setbuf, _IO_file_setbuf), + JUMP_INIT(sync, _IO_file_sync), + JUMP_INIT(doallocate, _IO_file_doallocate), + JUMP_INIT(read, _IO_cookie_read), + JUMP_INIT(write, _IO_cookie_write), + JUMP_INIT(seek, _IO_cookie_seek), + JUMP_INIT(close, _IO_cookie_close), + JUMP_INIT(stat, _IO_default_stat) +}; + + +_IO_FILE * +fopencookie (cookie, mode, io_functions) + void *cookie; + const char *mode; + _IO_cookie_io_functions_t io_functions; +{ + int read_write; + struct _IO_cookie_file *cfile; + + switch (*mode++) + { + case 'r': + read_write = _IO_NO_WRITES; + break; + case 'w': + read_write = _IO_NO_READS; + break; + case 'a': + read_write = _IO_NO_READS|_IO_IS_APPENDING; + break; + default: + return NULL; + } + if (mode[0] == '+' || (mode[0] == 'b' && mode[1] == '+')) + read_write &= _IO_IS_APPENDING; + + cfile = (struct _IO_cookie_file *) malloc (sizeof (struct _IO_cookie_file)); + if (cfile == NULL) + return NULL; + + _IO_init (&cfile->file, 0); + _IO_JUMPS (&cfile->file) = &_IO_cookie_jumps; + cfile->cookie = cookie; + cfile->io_functions = io_functions; + + _IO_file_init(&cfile->file); + + cfile->file._IO_file_flags = + _IO_mask_flags (&cfile->file, read_write, + _IO_NO_READS+_IO_NO_WRITES+_IO_IS_APPENDING); + + return &cfile->file; +} + diff --git a/libio/iofprintf.c b/libio/iofprintf.c new file mode 100644 index 0000000000..74e28263b5 --- /dev/null +++ b/libio/iofprintf.c @@ -0,0 +1,48 @@ +/* +Copyright (C) 1993 Free Software Foundation + +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 __STDC__ +#include <stdarg.h> +#else +#include <varargs.h> +#endif + +int +_IO_fprintf +#ifdef __STDC__ + (_IO_FILE *fp, const char* format, ...) +#else +(fp, format, va_alist) _IO_FILE *fp; char *format; va_dcl +#endif +{ + int ret; + va_list args; + CHECK_FILE (fp, -1); + _IO_va_start (args, format); + ret = _IO_vfprintf (fp, format, args); + va_end (args); + return ret; +} diff --git a/libio/iofputs.c b/libio/iofputs.c new file mode 100644 index 0000000000..62bc981e1d --- /dev/null +++ b/libio/iofputs.c @@ -0,0 +1,40 @@ +/* +Copyright (C) 1993 Free Software Foundation + +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> + +int +_IO_fputs (str, fp) + const char *str; + _IO_FILE *fp; +{ + _IO_size_t len = strlen (str); + CHECK_FILE (fp, EOF); + if (_IO_sputn( fp, str, len) != len) + return EOF; + return 1; +} + +weak_alias (_IO_fputs, fputs) diff --git a/libio/iofread.c b/libio/iofread.c new file mode 100644 index 0000000000..babe2c54cc --- /dev/null +++ b/libio/iofread.c @@ -0,0 +1,42 @@ +/* +Copyright (C) 1993, 1995 Free Software Foundation + +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" + +_IO_size_t +_IO_fread (buf, size, count, fp) + void *buf; + _IO_size_t size; + _IO_size_t count; + _IO_FILE* fp; +{ + _IO_size_t bytes_requested = size*count; + _IO_size_t bytes_read; + CHECK_FILE (fp, 0); + if (bytes_requested == 0) + return 0; + bytes_read = _IO_sgetn (fp, (char *) buf, bytes_requested); + return bytes_requested == bytes_read ? count : bytes_read / size; +} +weak_alias (_IO_fread, fread) diff --git a/libio/iofscanf.c b/libio/iofscanf.c new file mode 100644 index 0000000000..512d5e515e --- /dev/null +++ b/libio/iofscanf.c @@ -0,0 +1,50 @@ +/* +Copyright (C) 1993, 1995 Free Software Foundation + +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 __STDC__ +#include <stdarg.h> +#else +#include <varargs.h> +#endif + +int +_IO_fscanf +#ifdef __STDC__ + (_IO_FILE *fp, const char* format, ...) +#else +(fp, format, va_alist) _IO_FILE *fp; char *format; va_dcl +#endif +{ + int ret; + va_list args; + CHECK_FILE (fp, EOF); + _IO_va_start (args, format); + ret = _IO_vfscanf (fp, format, args, NULL); + va_end (args); + return ret; +} + +weak_alias (_IO_fscanf, fscanf) diff --git a/libio/iofsetpos.c b/libio/iofsetpos.c new file mode 100644 index 0000000000..72db3b1fa0 --- /dev/null +++ b/libio/iofsetpos.c @@ -0,0 +1,46 @@ +/* +Copyright (C) 1993, 1995 Free Software Foundation + +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_fsetpos (fp, posp) + _IO_FILE* fp; + const _IO_fpos_t *posp; +{ + CHECK_FILE (fp, EOF); + if (_IO_seekpos (fp, *posp, _IOS_INPUT|_IOS_OUTPUT) == _IO_pos_BAD) + { + /*ANSI explicily requires setting errno to a positive value on failure.*/ +#ifdef EIO + if (errno == 0) + errno = EIO; +#endif + return EOF; + } + return 0; +} + +weak_alias (_IO_fsetpos, fsetpos) diff --git a/libio/ioftell.c b/libio/ioftell.c new file mode 100644 index 0000000000..8af2ce7f1f --- /dev/null +++ b/libio/ioftell.c @@ -0,0 +1,47 @@ +/* +Copyright (C) 1993, 1995 Free Software Foundation + +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> +/* ANSI explicily requires setting errno to a positive value on failure. */ + +long int +_IO_ftell (fp) + _IO_FILE* fp; +{ + _IO_pos_t pos; + CHECK_FILE (fp, -1L); + pos = _IO_seekoff (fp, 0, _IO_seek_cur, 0); + if (pos == _IO_pos_BAD) + { +#ifdef EIO + if (errno == 0) + errno = EIO; +#endif + return -1L; + } + return _IO_pos_as_off (pos); +} + +weak_alias (_IO_ftell, ftell) diff --git a/libio/iofwrite.c b/libio/iofwrite.c new file mode 100644 index 0000000000..b8f02f2dd0 --- /dev/null +++ b/libio/iofwrite.c @@ -0,0 +1,48 @@ +/* +Copyright (C) 1993 Free Software Foundation + +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" + +_IO_size_t +_IO_fwrite (buf, size, count, fp) + const void* buf; + _IO_size_t size; + _IO_size_t count; + _IO_FILE *fp; +{ + _IO_size_t request = size*count; + _IO_size_t written; + CHECK_FILE (fp, 0); + if (request == 0) + return 0; + written = _IO_sputn (fp, (const char *) buf, request); + /* Many traditional implementations return 0 if size==0 && count > 0, + but ANSI seems to require us to return count in this case. */ + if (written == request) + return count; + else + return written/size; +} + +weak_alias (_IO_fwrite, fwrite) diff --git a/libio/iogetdelim.c b/libio/iogetdelim.c new file mode 100644 index 0000000000..a6894a5ae6 --- /dev/null +++ b/libio/iogetdelim.c @@ -0,0 +1,105 @@ +/* +Copyright (C) 1994 Free Software Foundation + +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. */ + +#ifdef __STDC__ +#include <stdlib.h> +#endif +#include "libioP.h" +#include <string.h> +#include <errno.h> + +/* Read up to (and including) a TERMINATOR from FP into *LINEPTR + (and null-terminate it). *LINEPTR is a pointer returned from malloc (or + NULL), pointing to *N characters of space. It is realloc'ed as + necessary. Returns the number of characters read (not including the + null terminator), or -1 on error or EOF. */ + +_IO_ssize_t +_IO_getdelim (lineptr, n, delimiter, fp) + char **lineptr; + _IO_size_t *n; + int delimiter; + _IO_FILE *fp; +{ + register _IO_ssize_t cur_len = 0; + _IO_ssize_t len; + + if (lineptr == NULL || n == NULL) + { +#ifdef EINVAL + errno = EINVAL; +#endif + return -1; + } + CHECK_FILE (fp, -1); + if (_IO_ferror (fp)) + return -1; + + if (*lineptr == NULL || *n == 0) + { + *n = 120; + *lineptr = (char *) malloc (*n); + if (*lineptr == NULL) + return -1; + } + + len = fp->_IO_read_end - fp->_IO_read_ptr; + if (len <= 0) + { + if (__underflow (fp) == EOF) + return -1; + len = fp->_IO_read_end - fp->_IO_read_ptr; + } + + for (;;) + { + _IO_size_t needed; + char *t; + t = (char *) memchr ((void *) fp->_IO_read_ptr, delimiter, len); + if (t != NULL) + len = (t - fp->_IO_read_ptr) + 1; + /* make enough space for len+1 (for final NUL) bytes. */ + needed = cur_len + len + 1; + if (needed > *n) + { + if (t == NULL && needed < 2 * *n) + needed = 2 * *n; /* Be generous. */ + *n = needed; + *lineptr = (char *) realloc (*lineptr, needed); + if (*lineptr == NULL) + return -1; + } + memcpy (*lineptr + cur_len, (void *) fp->_IO_read_ptr, len); + fp->_IO_read_ptr += len; + cur_len += len; + if (t != NULL || __underflow (fp) == EOF) + break; + len = fp->_IO_read_end - fp->_IO_read_ptr; + } + lineptr[cur_len] = '\0'; + return cur_len; +} + +weak_alias (_IO_getdelim, __getdelim) +weak_alias (_IO_getdelim, getdelim) diff --git a/libio/iogetline.c b/libio/iogetline.c new file mode 100644 index 0000000000..85dff7e3e7 --- /dev/null +++ b/libio/iogetline.c @@ -0,0 +1,74 @@ +/* +Copyright (C) 1993 Free Software Foundation + +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 GNU CC; see the file COPYING. If not, write to +the Free Software Foundation, 675 Mass Ave, Cambridge, MA 02139, 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> + +/* 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 +DEFUN(_IO_getline, (fp, buf, n, delim, extract_delim), + _IO_FILE *fp AND char* buf AND _IO_size_t n + AND int delim AND int extract_delim) +{ + register char *ptr = buf; + do + { + _IO_ssize_t len = fp->_IO_read_end - fp->_IO_read_ptr; + char *t; + if (len <= 0) + if (__underflow(fp) == EOF) + break; + else + len = fp->_IO_read_end - fp->_IO_read_ptr; + if (len >= n) + len = n; + t = (char*)memchr((void*)fp->_IO_read_ptr, delim, len); + if (t != NULL) + { + _IO_size_t old_len = ptr-buf; + len = t - fp->_IO_read_ptr; + if (extract_delim >= 0) + { + t++; + if (extract_delim > 0) + len++; + } + memcpy((void*)ptr, (void*)fp->_IO_read_ptr, len); + fp->_IO_read_ptr = t; + return old_len + len; + } + memcpy((void*)ptr, (void*)fp->_IO_read_ptr, len); + fp->_IO_read_ptr += len; + ptr += len; + n -= len; + } while (n != 0); + return ptr - buf; +} diff --git a/libio/iogets.c b/libio/iogets.c new file mode 100644 index 0000000000..419342fb12 --- /dev/null +++ b/libio/iogets.c @@ -0,0 +1,49 @@ +/* +Copyright (C) 1993 Free Software Foundation + +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 <limits.h> + +char* +_IO_gets (buf) + char* buf; +{ + _IO_size_t count; + int ch = _IO_getc (_IO_stdin); + if (ch == EOF) + return NULL; + if (ch == '\n') + count = 0; + else + { + buf[0] = (char)ch; + count = _IO_getline (_IO_stdin, buf + 1, INT_MAX, '\n', 0) + 1; + if (_IO_stdin->_IO_file_flags & _IO_ERR_SEEN) + return NULL; + } + buf[count] = 0; + return buf; +} + +weak_alias (_IO_gets, gets) diff --git a/libio/iolibio.h b/libio/iolibio.h new file mode 100644 index 0000000000..e5de77ea85 --- /dev/null +++ b/libio/iolibio.h @@ -0,0 +1,53 @@ +#include "libio.h" + +/* These emulate stdio functionality, but with a different name + (_IO_ungetc instead of ungetc), and using _IO_FILE instead of FILE. */ + +#ifdef __cplusplus +extern "C" { +#endif + +extern int _IO_fclose __P((_IO_FILE*)); +extern _IO_FILE *_IO_fdopen __P((int, const char*)); +extern int _IO_fflush __P((_IO_FILE*)); +extern int _IO_fgetpos __P((_IO_FILE*, _IO_fpos_t*)); +extern char* _IO_fgets __P((char*, int, _IO_FILE*)); +extern _IO_FILE *_IO_fopen __P((const char*, const char*)); +extern int _IO_fprintf __P((_IO_FILE*, const char*, ...)); +extern int _IO_fputs __P((const char*, _IO_FILE*)); +extern int _IO_fsetpos __P((_IO_FILE*, const _IO_fpos_t *)); +extern long int _IO_ftell __P((_IO_FILE*)); +extern _IO_size_t _IO_fread __P((void*, _IO_size_t, _IO_size_t, _IO_FILE*)); +extern _IO_size_t _IO_fwrite __P((const void*, + _IO_size_t, _IO_size_t, _IO_FILE*)); +extern char* _IO_gets __P((char*)); +extern void _IO_perror __P((const char*)); +extern int _IO_printf __P((const char*, ...)); +extern int _IO_puts __P((const char*)); +extern int _IO_scanf __P((const char*, ...)); +extern void _IO_setbuffer __P((_IO_FILE *, char*, _IO_size_t)); +extern int _IO_setvbuf __P((_IO_FILE*, char*, int, _IO_size_t)); +extern int _IO_sscanf __P((const char*, const char*, ...)); +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)); +#ifndef _IO_pos_BAD +#define _IO_pos_BAD ((_IO_fpos_t)(-1)) +#endif +#define _IO_clearerr(FP) ((FP)->_flags &= ~(_IO_ERR_SEEN|_IO_EOF_SEEN)) +#define _IO_fseek(__fp, __offset, __whence) \ + (_IO_seekoff(__fp, __offset, __whence, _IOS_INPUT|_IOS_OUTPUT) == _IO_pos_BAD ? EOF : 0) +#define _IO_rewind(FILE) (void)_IO_seekoff(FILE, 0, 0, _IOS_INPUT|_IOS_OUTPUT) +#define _IO_vprintf(FORMAT, ARGS) _IO_vfprintf(_IO_stdout, FORMAT, ARGS) +#define _IO_freopen(FILENAME, MODE, FP) \ + (_IO_file_close_it(FP), _IO_file_fopen(FP, FILENAME, MODE)) +#define _IO_fileno(FP) ((FP)->_fileno) +extern _IO_FILE* _IO_popen __P((const char*, const char*)); +#define _IO_pclose _IO_fclose +#define _IO_setbuf(_FP, _BUF) _IO_setbuffer(_FP, _BUF, _IO_BUFSIZ) +#define _IO_setlinebuf(_FP) _IO_setvbuf(_FP, NULL, 1, 0) + +#ifdef __cplusplus +} +#endif diff --git a/libio/iopadn.c b/libio/iopadn.c new file mode 100644 index 0000000000..94166a3eb1 --- /dev/null +++ b/libio/iopadn.c @@ -0,0 +1,65 @@ +/* +Copyright (C) 1993 Free Software Foundation + +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 GNU CC; see the file COPYING. If not, write to +the Free Software Foundation, 675 Mass Ave, Cambridge, MA 02139, 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 char const blanks[PADSIZE] = +{' ',' ',' ',' ',' ',' ',' ',' ',' ',' ',' ',' ',' ',' ',' ',' '}; +static char const zeroes[PADSIZE] = +{'0','0','0','0','0','0','0','0','0','0','0','0','0','0','0','0'}; + +_IO_ssize_t +DEFUN(_IO_padn, (fp, pad, count), + _IO_FILE *fp AND int pad AND _IO_ssize_t count) +{ + char padbuf[PADSIZE]; + const char *padptr; + register int i; + _IO_size_t written = 0, w; + + if (pad == ' ') + padptr = blanks; + else if (pad == '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, padptr, PADSIZE); + written += w; + if (w != PADSIZE) + return written; + } + + if (i > 0) + { + w = _IO_sputn(fp, padptr, i); + written += w; + } + return written; +} diff --git a/libio/ioprims.c b/libio/ioprims.c new file mode 100644 index 0000000000..d17c10a168 --- /dev/null +++ b/libio/ioprims.c @@ -0,0 +1,73 @@ +/* +Copyright (C) 1993 Free Software Foundation + +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 GNU CC; see the file COPYING. If not, write to +the Free Software Foundation, 675 Mass Ave, Cambridge, MA 02139, 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. */ + +/* I/O OS-level primitives. + Needs to be replaced if not using Unix. + Also needs to be replaced if avoiding name-space pollution + (in which case read would be defined in terms of _IO_read, + rather than vice versa). */ + +#include "libioP.h" +#include <unistd.h> +#include <sys/types.h> +#include <sys/stat.h> + +#ifdef TODO +/* Add open, isatty */ +#endif + +_IO_ssize_t +DEFUN(_IO_read, (fildes, buf, nbyte), + int fildes AND void *buf AND _IO_size_t nbyte) +{ + return __read (fildes, buf, nbyte); +} + +_IO_ssize_t +DEFUN(_IO_write, (fildes, buf, nbyte), + int fildes AND const void *buf AND _IO_size_t nbyte) +{ + return __write (fildes, buf, nbyte); +} + +_IO_off_t +DEFUN(_IO_lseek, (fildes, offset, whence), + int fildes AND _IO_off_t offset AND int whence) +{ + return __lseek (fildes, offset, whence); +} + +int +DEFUN(_IO_close, (fildes), + int fildes) +{ + return __close (fildes); +} + +int +DEFUN(_IO_fstat, (fildes, buf), + int fildes AND struct stat *buf) +{ + return __fstat (fildes, buf); +} diff --git a/libio/ioputs.c b/libio/ioputs.c new file mode 100644 index 0000000000..129da1d821 --- /dev/null +++ b/libio/ioputs.c @@ -0,0 +1,38 @@ +/* Copyright (C) 1993 Free Software Foundation + +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> + +int +_IO_puts (str) + const char *str; +{ + _IO_size_t len = strlen (str); + if (_IO_sputn (_IO_stdout, str, len) != len) + return EOF; + if (_IO_putc ('\n', _IO_stdout) == EOF) + return EOF; + return len+1; +} +weak_alias (_IO_puts, puts) diff --git a/libio/ioseekoff.c b/libio/ioseekoff.c new file mode 100644 index 0000000000..1de4f7bdc9 --- /dev/null +++ b/libio/ioseekoff.c @@ -0,0 +1,43 @@ +/* +Copyright (C) 1993 Free Software Foundation + +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 GNU CC; see the file COPYING. If not, write to +the Free Software Foundation, 675 Mass Ave, Cambridge, MA 02139, 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> + +_IO_pos_t +DEFUN(_IO_seekoff, (fp, offset, dir, mode), + _IO_FILE* fp AND _IO_off_t offset AND int dir AND int mode) +{ + /* If we have a backup buffer, get rid of it, since the __seekoff + callback may not know to do the right thing about it. + This may be over-kill, but it'll do for now. TODO */ + + if (_IO_have_backup (fp)) + { + if (dir == _IO_seek_cur && _IO_in_backup (fp)) + offset -= fp->_IO_read_end - fp->_IO_read_ptr; + _IO_free_backup_area (fp); + } + + return _IO_SEEKOFF (fp, offset, dir, mode); +} diff --git a/libio/ioseekpos.c b/libio/ioseekpos.c new file mode 100644 index 0000000000..be6863370a --- /dev/null +++ b/libio/ioseekpos.c @@ -0,0 +1,39 @@ +/* +Copyright (C) 1993 Free Software Foundation + +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 GNU CC; see the file COPYING. If not, write to +the Free Software Foundation, 675 Mass Ave, Cambridge, MA 02139, 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> + +_IO_pos_t +DEFUN(_IO_seekpos, (fp, pos, mode), + _IO_FILE* fp AND _IO_pos_t pos AND int mode) +{ + /* If we have a backup buffer, get rid of it, since the __seekoff + callback may not know to do the right thing about it. + This may be over-kill, but it'll do for now. TODO */ + + if (_IO_have_backup (fp)) + _IO_free_backup_area (fp); + + return _IO_SEEKPOS (fp, pos, mode); +} diff --git a/libio/iosetbuffer.c b/libio/iosetbuffer.c new file mode 100644 index 0000000000..0ad38111d6 --- /dev/null +++ b/libio/iosetbuffer.c @@ -0,0 +1,38 @@ +/* +Copyright (C) 1993 Free Software Foundation + +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" + +void +_IO_setbuffer (fp, buf, size) + _IO_FILE *fp; + char *buf; + _IO_size_t size; +{ + CHECK_FILE (fp, ); + fp->_flags &= ~_IO_LINE_BUF; + if (!buf) + size = 0; + (void) _IO_SETBUF (fp, buf, size); +} diff --git a/libio/iosetvbuf.c b/libio/iosetvbuf.c new file mode 100644 index 0000000000..316179e330 --- /dev/null +++ b/libio/iosetvbuf.c @@ -0,0 +1,80 @@ +/* +Copyright (C) 1993 Free Software Foundation + +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 _IOFBF 0 /* Fully buffered. */ +#define _IOLBF 1 /* Line buffered. */ +#define _IONBF 2 /* No buffering. */ + +int +_IO_setvbuf (fp, buf, mode, size) + _IO_FILE* fp; + char* buf; + int mode; + _IO_size_t size; +{ + CHECK_FILE (fp, EOF); + switch (mode) + { + case _IOFBF: + fp->_IO_file_flags &= ~_IO_LINE_BUF; + if (buf == NULL) + { + if (fp->_IO_buf_base == NULL) + { + /* There is no flag to distinguish between "fully buffered + mode has been explicitly set" as opposed to "line + buffering has not been explicitly set". In both + cases, _IO_LINE_BUF is off. If this is a tty, and + _IO_filedoalloc later gets called, it cannot know if + it should set the _IO_LINE_BUF flag (because that is + the default), or not (because we have explicitly asked + for fully buffered mode). So we make sure a buffer + gets allocated now, and explicitly turn off line + buffering. + + A possibly cleaner alternative would be to add an + extra flag, but then flags are a finite resource. */ + if (_IO_DOALLOCATE (fp) < 0) + return EOF; + fp->_IO_file_flags &= ~_IO_LINE_BUF; + } + return 0; + } + break; + case _IOLBF: + fp->_IO_file_flags |= _IO_LINE_BUF; + if (buf == NULL) + return 0; + break; + case _IONBF: + buf = NULL; + size = 0; + break; + default: + return EOF; + } + return _IO_SETBUF (fp, buf, size) == NULL ? EOF : 0; +} diff --git a/libio/iosprintf.c b/libio/iosprintf.c new file mode 100644 index 0000000000..b873eb4455 --- /dev/null +++ b/libio/iosprintf.c @@ -0,0 +1,47 @@ +/* +Copyright (C) 1993 Free Software Foundation + +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 __STDC__ +#include <stdarg.h> +#else +#include <varargs.h> +#endif + +int +_IO_sprintf +#ifdef __STDC__ + (char *string, const char* format, ...) +#else +(string, format, va_alist) char *string; char *format; va_dcl +#endif +{ + int ret; + va_list args; + _IO_va_start(args, format); + ret = _IO_vsprintf(string, format, args); + va_end(args); + return ret; +} diff --git a/libio/ioungetc.c b/libio/ioungetc.c new file mode 100644 index 0000000000..1a6988ef16 --- /dev/null +++ b/libio/ioungetc.c @@ -0,0 +1,38 @@ +/* +Copyright (C) 1993 Free Software Foundation + +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" + +int +_IO_ungetc (c, fp) + int c; + _IO_FILE *fp; +{ + CHECK_FILE (fp, EOF); + if (c == EOF) + return EOF; + return _IO_sputbackc (fp, (unsigned char) c); +} + +weak_alias (_IO_ungetc, ungetc) diff --git a/libio/iovsprintf.c b/libio/iovsprintf.c new file mode 100644 index 0000000000..182c4ff306 --- /dev/null +++ b/libio/iovsprintf.c @@ -0,0 +1,44 @@ +/* +Copyright (C) 1993 Free Software Foundation + +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" + +int +_IO_vsprintf (string, format, args) + char *string; + const char *format; + _IO_va_list args; +{ + _IO_strfile sf; + int ret; + _IO_init ((_IO_FILE *) &sf, 0); + _IO_JUMPS ((_IO_FILE *) &sf) = &_IO_str_jumps; + _IO_str_init_static ((_IO_FILE *) &sf, string, -1, string); + ret = _IO_vfprintf ((_IO_FILE *) &sf, format, args); + _IO_putc('\0', (_IO_FILE *) &sf); + return ret; +} + +weak_alias (_IO_vsprintf, vsprintf) diff --git a/libio/iovsscanf.c b/libio/iovsscanf.c new file mode 100644 index 0000000000..61eeed2f3e --- /dev/null +++ b/libio/iovsscanf.c @@ -0,0 +1,38 @@ +/* +Copyright (C) 1993 Free Software Foundation + +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 GNU CC; see the file COPYING. If not, write to +the Free Software Foundation, 675 Mass Ave, Cambridge, MA 02139, 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" + +int +DEFUN(_IO_vsscanf, (string, format, args), + const char *string AND const char *format AND _IO_va_list args) +{ + _IO_strfile sf; + _IO_init((_IO_FILE*)&sf, 0); + _IO_JUMPS((_IO_FILE*)&sf) = &_IO_str_jumps; + _IO_str_init_static ((_IO_FILE*)&sf, (char*)string, 0, NULL); + return _IO_vfscanf((_IO_FILE*)&sf, format, args, NULL); +} +weak_alias (_IO_vsscanf, vsscanf) diff --git a/libio/libio.h b/libio/libio.h new file mode 100644 index 0000000000..405036dfb6 --- /dev/null +++ b/libio/libio.h @@ -0,0 +1,272 @@ +/* +Copyright (C) 1991, 1992, 1993, 1994, 1995 Free Software Foundation + +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. */ + +/* This is part of the iostream library. Written by Per Bothner. */ + +#ifndef _IO_STDIO_H +#define _IO_STDIO_H + +#include <_G_config.h> +#define _IO_pos_t _G_fpos_t /* obsolete */ +#define _IO_fpos_t _G_fpos_t +#define _IO_size_t _G_size_t +#define _IO_ssize_t _G_ssize_t +#define _IO_off_t _G_off_t +#define _IO_pid_t _G_pid_t +#define _IO_uid_t _G_uid_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 + +#ifdef _G_NEED_STDARG_H +/* This define avoids name pollution if we're using GNU stdarg.h */ +#define __need___va_list +#include <stdarg.h> +#ifdef __GNUC_VA_LIST +#undef _IO_va_list +#define _IO_va_list __gnuc_va_list +#endif /* __GNUC_VA_LIST */ +#endif + +#ifndef __P +#ifdef __STDC__ +#define __P(protos) protos +#else +#define __P(protos) () +#endif +#endif /*!__P*/ + +/* For backward compatibility */ +#ifndef _PARAMS +#define _PARAMS(protos) __P(protos) +#endif /*!_PARAMS*/ + +#ifndef __STDC__ +#define const +#endif +#define _IO_UNIFIED_JUMPTABLES 1 + +#if 0 +#ifdef _IO_NEED_STDARG_H +#include <stdarg.h> +#endif +#endif + +#ifndef EOF +#define EOF (-1) +#endif +#ifndef NULL +#if !defined(__cplusplus) || defined(__GNUC__) +#define NULL ((void*)0) +#else +#define NULL (0) +#endif +#endif + +#define _IOS_INPUT 1 +#define _IOS_OUTPUT 2 +#define _IOS_ATEND 4 +#define _IOS_APPEND 8 +#define _IOS_TRUNC 16 +#define _IOS_NOCREATE 32 +#define _IOS_NOREPLACE 64 +#define _IOS_BIN 128 + +/* Magic numbers and bits for the _flags field. + The magic numbers use the high-order bits of _flags; + the remaining bits are abailable for variable flags. + Note: The magic numbers must all be negative if stdio + emulation is desired. */ + +#define _IO_MAGIC 0xFBAD0000 /* Magic number */ +#define _OLD_STDIO_MAGIC 0xFABC0000 /* Emulate old stdio. */ +#define _IO_MAGIC_MASK 0xFFFF0000 +#define _IO_USER_BUF 1 /* User owns buffer; don't delete it on close. */ +#define _IO_UNBUFFERED 2 +#define _IO_NO_READS 4 /* Reading not allowed */ +#define _IO_NO_WRITES 8 /* Writing not allowd */ +#define _IO_EOF_SEEN 0x10 +#define _IO_ERR_SEEN 0x20 +#define _IO_DELETE_DONT_CLOSE 0x40 /* Don't call close(_fileno) on cleanup. */ +#define _IO_LINKED 0x80 /* Set if linked (using _chain) to streambuf::_list_all.*/ +#define _IO_IN_BACKUP 0x100 +#define _IO_LINE_BUF 0x200 +#define _IO_TIED_PUT_GET 0x400 /* Set if put and get pointer logicly tied. */ +#define _IO_CURRENTLY_PUTTING 0x800 +#define _IO_IS_APPENDING 0x1000 +#define _IO_IS_FILEBUF 0x2000 + +/* These are "formatting flags" matching the iostream fmtflags enum values. */ +#define _IO_SKIPWS 01 +#define _IO_LEFT 02 +#define _IO_RIGHT 04 +#define _IO_INTERNAL 010 +#define _IO_DEC 020 +#define _IO_OCT 040 +#define _IO_HEX 0100 +#define _IO_SHOWBASE 0200 +#define _IO_SHOWPOINT 0400 +#define _IO_UPPERCASE 01000 +#define _IO_SHOWPOS 02000 +#define _IO_SCIENTIFIC 04000 +#define _IO_FIXED 010000 +#define _IO_UNITBUF 020000 +#define _IO_STDIO 040000 +#define _IO_DONT_CLOSE 0100000 + + +struct _IO_jump_t; struct _IO_FILE; + +/* Define the user-visible type, with user-friendly member names. */ +typedef struct +{ + _IO_ssize_t (*read) __P ((struct _IO_FILE *, void *, _IO_ssize_t)); + _IO_ssize_t (*write) __P ((struct _IO_FILE *, const void *, _IO_ssize_t)); + _IO_fpos_t (*seek) __P ((struct _IO_FILE *, _IO_off_t, int)); + int (*close) __P ((struct _IO_FILE *)); +} _IO_cookie_io_functions_t; + + +/* The reentrant version of the libio implementation needs a semaphore for + each _IO_FILE struture. Because we don't know how the semaphore + will be implemented we try to be very general. */ +struct _IO_lock_t { + void *ptr; + short int field1; + short int field2; +}; + +/* A streammarker remembers a position in a buffer. */ + +struct _IO_marker { + struct _IO_marker *_next; + struct _IO_FILE *_sbuf; + /* If _pos >= 0 + it points to _buf->Gbase()+_pos. FIXME comment */ + /* if _pos < 0, it points to _buf->eBptr()+_pos. FIXME comment */ + int _pos; +#if 0 + void set_streampos(streampos sp) { _spos = sp; } + void set_offset(int offset) { _pos = offset; _spos = (streampos)(-2); } + public: + streammarker(streambuf *sb); + ~streammarker(); + int saving() { return _spos == -2; } + int delta(streammarker&); + int delta(); +#endif +}; + +struct _IO_FILE { + int _flags; /* High-order word is _IO_MAGIC; rest is flags. */ +#define _IO_file_flags _flags + + /* The following pointers correspond to the C++ streambuf protocol. */ + char* _IO_read_ptr; /* Current read pointer */ + char* _IO_read_end; /* End of get area. */ + char* _IO_read_base; /* Start of putback+get area. */ + char* _IO_write_base; /* Start of put area. */ + char* _IO_write_ptr; /* Current put pointer. */ + char* _IO_write_end; /* End of put area. */ + char* _IO_buf_base; /* Start of reserve area. */ + char* _IO_buf_end; /* End of reserve area. */ + /* The following fields are used to support backing up and undo. */ + char *_IO_save_base; /* Pointer to start of non-current get area. */ + char *_IO_backup_base; /* Pointer to first valid character of backup area */ + char *_IO_save_end; /* Pointer to end of non-current get area. */ + + struct _IO_marker *_markers; + + struct _IO_FILE *_chain; + +#if !_IO_UNIFIED_JUMPTABLES + struct _IO_jump_t *_jumps; /* Jump table */ +#endif + + int _fileno; + int _blksize; + _IO_off_t _offset; + +#define __HAVE_COLUMN /* temporary */ + /* 1+column number of pbase(); 0 is unknown. */ + unsigned short _cur_column; + char _unused; + char _shortbuf[1]; + + /* char* _save_gptr; char* _save_egptr; */ + + struct _IO_lock_t _IO_lock; +}; + +#ifndef __cplusplus +typedef struct _IO_FILE _IO_FILE; +#endif + +struct _IO_FILE_plus; +extern struct _IO_FILE_plus _IO_stdin_, _IO_stdout_, _IO_stderr_; +#define _IO_stdin ((_IO_FILE*)(&_IO_stdin_)) +#define _IO_stdout ((_IO_FILE*)(&_IO_stdout_)) +#define _IO_stderr ((_IO_FILE*)(&_IO_stderr_)) + +#ifdef __cplusplus +extern "C" { +#endif + +extern int __underflow __P((_IO_FILE*)); +extern int __uflow __P((_IO_FILE*)); +extern int __overflow __P((_IO_FILE*, int)); + +#define _IO_getc(_fp) \ + ((_fp)->_IO_read_ptr >= (_fp)->_IO_read_end ? __uflow(_fp) \ + : *(unsigned char*)(_fp)->_IO_read_ptr++) +#define _IO_peekc(_fp) \ + ((_fp)->_IO_read_ptr >= (_fp)->_IO_read_end \ + && __underflow(_fp) == EOF ? EOF \ + : *(unsigned char*)(_fp)->_IO_read_ptr) + +#define _IO_putc(_ch, _fp) \ + (((_fp)->_IO_write_ptr >= (_fp)->_IO_write_end) \ + ? __overflow(_fp, (unsigned char)(_ch)) \ + : (unsigned char)(*(_fp)->_IO_write_ptr++ = (_ch))) + +#define _IO_feof(__fp) (((__fp)->_flags & _IO_EOF_SEEN) != 0) +#define _IO_ferror(__fp) (((__fp)->_flags & _IO_ERR_SEEN) != 0) + +/* This one is for Emacs. */ +#define _IO_PENDING_OUTPUT_COUNT(_fp) \ + ((_fp)->_IO_write_ptr - (_fp)->_IO_write_base) + +extern int _IO_vfscanf __P((_IO_FILE*, const char*, _IO_va_list, int*)); +extern int _IO_vfprintf __P((_IO_FILE*, const char*, _IO_va_list)); +extern _IO_ssize_t _IO_padn __P((_IO_FILE *, int, _IO_ssize_t)); +extern _IO_size_t _IO_sgetn __P((_IO_FILE *, void*, _IO_size_t)); + +extern void _IO_free_backup_area __P((_IO_FILE*)); + +#ifdef __cplusplus +} +#endif + +#endif /* _IO_STDIO_H */ diff --git a/libio/libioP.h b/libio/libioP.h new file mode 100644 index 0000000000..a955151ade --- /dev/null +++ b/libio/libioP.h @@ -0,0 +1,397 @@ +/* +Copyright (C) 1993 Free Software Foundation + +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 <errno.h> +#ifndef errno +extern int errno; +#endif + +#include "iolibio.h" + +#if defined (__STDC__) || defined (_AIX) || (defined (__mips) && defined (_SYSTYPE_SVR4)) || defined(__cplusplus) +/* All known AIX compilers implement these things (but don't always + define __STDC__). The RISC/OS MIPS compiler defines these things + in SVR4 mode, but does not define __STDC__. */ + +#define AND , +#define DEFUN(name, arglist, args) name(args) +#define DEFUN_VOID(name) name(void) + +#else /* Not ANSI C. */ + +#define AND ; +#ifndef const /* some systems define it in header files for non-ansi mode */ +#define const +#endif +#define DEFUN(name, arglist, args) name arglist args; +#define DEFUN_VOID(name) name() +#endif /* ANSI C. */ + +#ifdef __cplusplus +extern "C" { +#endif + +#define _IO_seek_set 0 +#define _IO_seek_cur 1 +#define _IO_seek_end 2 + +typedef int (*_IO_overflow_t) __P((_IO_FILE*, int)); +typedef int (*_IO_underflow_t) __P((_IO_FILE*)); +typedef _IO_size_t (*_IO_xsputn_t) __P((_IO_FILE*,const void*,_IO_size_t)); +typedef _IO_size_t (*_IO_xsgetn_t) __P((_IO_FILE*, void*, _IO_size_t)); +typedef _IO_ssize_t (*_IO_read_t) __P((_IO_FILE*, void*, _IO_ssize_t)); +typedef _IO_ssize_t (*_IO_write_t) __P((_IO_FILE*,const void*,_IO_ssize_t)); +typedef int (*_IO_stat_t) __P((_IO_FILE*, void*)); +typedef _IO_fpos_t (*_IO_seek_t) __P((_IO_FILE*, _IO_off_t, int)); +typedef int (*_IO_doallocate_t) __P((_IO_FILE*)); +typedef int (*_IO_pbackfail_t) __P((_IO_FILE*, int)); +typedef _IO_FILE* (*_IO_setbuf_t) __P((_IO_FILE*, char *, _IO_ssize_t)); +typedef int (*_IO_sync_t) __P((_IO_FILE*)); +typedef void (*_IO_finish_t) __P((_IO_FILE*)); /* finalize */ +typedef int (*_IO_close_t) __P((_IO_FILE*)); /* finalize */ +typedef _IO_fpos_t (*_IO_seekoff_t) __P((_IO_FILE*, _IO_off_t, int, int)); + +/* The _IO_seek_cur and _IO_seek_end options are not allowed. */ +typedef _IO_fpos_t (*_IO_seekpos_t) __P((_IO_FILE*, _IO_fpos_t, int)); + +#if !_IO_UNIFIED_JUMPTABLES +#define _IO_JUMPS(THIS) (THIS)->_jumps +#else +#define _IO_JUMPS(THIS) ((struct _IO_FILE_plus*)(THIS))->vtable +#endif + +#if !_IO_UNIFIED_JUMPTABLES +#define JUMP_FIELD(TYPE, NAME) TYPE NAME +#define JUMP0(FUNC, THIS) _IO_JUMPS(THIS)->FUNC(THIS) +#define JUMP1(FUNC, THIS, X1) _IO_JUMPS(THIS)->FUNC(THIS, X1) +#define JUMP2(FUNC, THIS, X1, X2) _IO_JUMPS(THIS)->FUNC(THIS, X1, X2) +#define JUMP3(FUNC, THIS, X1, X2, X3) _IO_JUMPS(THIS)->FUNC(THIS, X1, X2, X3) +#define JUMP_INIT(NAME, VALUE) VALUE +#else +#define JUMP_FIELD(TYPE, NAME) struct { short delta1, delta2; TYPE pfn; } NAME +#define JUMP0(FUNC, THIS) _IO_JUMPS(THIS)->FUNC.pfn(THIS) +#define JUMP1(FUNC, THIS, X1) _IO_JUMPS(THIS)->FUNC.pfn(THIS, X1) +#define JUMP2(FUNC, THIS, X1, X2) _IO_JUMPS(THIS)->FUNC.pfn(THIS, X1, X2) +#define JUMP3(FUNC, THIS, X1,X2,X3) _IO_JUMPS(THIS)->FUNC.pfn(THIS, X1,X2, X3) +#define JUMP_INIT(NAME, VALUE) {0, 0, VALUE} +#endif +#define JUMP_INIT_DUMMY JUMP_INIT(dummy, 0) + +#define _IO_FINISH(FP) JUMP0(__finish, FP) +#define _IO_OVERFLOW(FP, CH) JUMP1(__overflow, FP, CH) +#define _IO_UNDERFLOW(FP) JUMP0(__underflow, FP) +#define _IO_UFLOW(FP) JUMP0(__uflow, FP) +#define _IO_PBACKFAIL(FP, CH) JUMP1(__pbackfail, FP, CH) +#define _IO_XSPUTN(FP, DATA, N) JUMP2(__xsputn, FP, DATA, N) +#define _IO_XSGETN(FP, DATA, N) JUMP2(__xsgetn, FP, DATA, N) +#define _IO_SEEKOFF(FP, OFF, DIR, MODE) JUMP3(__seekoff, FP, OFF, DIR, MODE) +#define _IO_SEEKPOS(FP, POS, FLAGS) JUMP2(__seekpos, FP, POS, FLAGS) +#define _IO_SETBUF(FP, BUFFER, LENGTH) JUMP2(__setbuf, FP, BUFFER, LENGTH) +#define _IO_SYNC(FP) JUMP0(__sync, FP) +#define _IO_DOALLOCATE(FP) JUMP0(__doallocate, FP) +#define _IO_SYSREAD(FP, DATA, LEN) JUMP2(__read, FP, DATA, LEN) +#define _IO_SYSWRITE(FP, DATA, LEN) JUMP2(__write, FP, DATA, LEN) +#define _IO_SYSSEEK(FP, OFFSET, MODE) JUMP2(__seek, FP, OFFSET, MODE) +#define _IO_SYSCLOSE(FP) JUMP0(__close, FP) +#define _IO_SYSSTAT(FP, BUF) JUMP1(__stat, FP, BUF) + +#define _IO_CHAR_TYPE char /* unsigned char ? */ +#define _IO_INT_TYPE int + +struct _IO_jump_t { + JUMP_FIELD(_G_size_t, __dummy); + JUMP_FIELD(_IO_finish_t, __finish); + JUMP_FIELD(_IO_overflow_t, __overflow); + JUMP_FIELD(_IO_underflow_t, __underflow); + JUMP_FIELD(_IO_underflow_t, __uflow); + JUMP_FIELD(_IO_pbackfail_t, __pbackfail); + /* showmany */ + JUMP_FIELD(_IO_xsputn_t, __xsputn); + JUMP_FIELD(_IO_xsgetn_t, __xsgetn); + JUMP_FIELD(_IO_seekoff_t, __seekoff); + JUMP_FIELD(_IO_seekpos_t, __seekpos); + JUMP_FIELD(_IO_setbuf_t, __setbuf); + JUMP_FIELD(_IO_sync_t, __sync); + JUMP_FIELD(_IO_doallocate_t, __doallocate); + JUMP_FIELD(_IO_read_t, __read); + JUMP_FIELD(_IO_write_t, __write); + JUMP_FIELD(_IO_seek_t, __seek); + JUMP_FIELD(_IO_close_t, __close); + JUMP_FIELD(_IO_stat_t, __stat); +#if 0 + get_column; + set_column; +#endif +}; + +/* We always allocate an extra word following an _IO_FILE. + This is for compatibility with C++ streambuf; the word can + be used to smash to a pointer to a virtual function table. */ + +struct _IO_FILE_plus { + _IO_FILE file; +#if _IO_UNIFIED_JUMPTABLES + const struct _IO_jump_t *vtable; +#else + const void *vtable; +#endif +}; + +/* Generic functions */ + +extern _IO_fpos_t _IO_seekoff __P((_IO_FILE*, _IO_off_t, int, int)); +extern _IO_fpos_t _IO_seekpos __P((_IO_FILE*, _IO_fpos_t, int)); + +extern int _IO_switch_to_get_mode __P((_IO_FILE*)); +extern void _IO_init __P((_IO_FILE*, int)); +extern int _IO_sputbackc __P((_IO_FILE*, int)); +extern int _IO_sungetc __P((_IO_FILE*)); +extern void _IO_un_link __P((_IO_FILE*)); +extern void _IO_link_in __P((_IO_FILE *)); +extern void _IO_doallocbuf __P((_IO_FILE*)); +extern void _IO_unsave_markers __P((_IO_FILE*)); +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) + +/* Marker-related function. */ + +extern void _IO_init_marker __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_seekmark __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 int _IO_default_doallocate __P((_IO_FILE*)); +extern void _IO_default_finish __P((_IO_FILE *)); +extern int _IO_default_pbackfail __P((_IO_FILE*, int)); +extern _IO_FILE* _IO_default_setbuf __P((_IO_FILE *, char*, _IO_ssize_t)); +extern _IO_size_t _IO_default_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_fpos_t _IO_default_seekoff __P((_IO_FILE*, _IO_off_t, int, int)); +extern _IO_fpos_t _IO_default_seekpos __P((_IO_FILE*, _IO_fpos_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_fpos_t _IO_default_seek __P((_IO_FILE*, _IO_off_t, int)); +extern int _IO_default_sync __P((_IO_FILE*)); +#define _IO_default_close ((_IO_close_t)_IO_default_sync) + +extern struct _IO_jump_t _IO_file_jumps; +extern struct _IO_jump_t _IO_streambuf_jumps; +extern struct _IO_jump_t _IO_proc_jumps; +extern struct _IO_jump_t _IO_str_jumps; +extern int _IO_do_write __P((_IO_FILE*, const char*, _IO_size_t)); +extern int _IO_flush_all __P((void)); +extern void _IO_cleanup __P((void)); +extern void _IO_flush_all_linebuffered __P((void)); + +#define _IO_do_flush(_f) \ + _IO_do_write(_f, (_f)->_IO_write_base, \ + (_f)->_IO_write_ptr-(_f)->_IO_write_base) +#define _IO_in_put_mode(_fp) ((_fp)->_flags & _IO_CURRENTLY_PUTTING) +#define _IO_mask_flags(fp, f, mask) \ + ((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_setp(__fp, __p, __ep) \ + ((__fp)->_IO_write_base = (__fp)->_IO_write_ptr = __p, (__fp)->_IO_write_end = (__ep)) +#define _IO_have_backup(fp) ((fp)->_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(p) ((fp)->_IO_buf_end - (fp)->_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_fpos_t _IO_file_seekoff __P((_IO_FILE*, _IO_off_t, int, int)); +extern _IO_size_t _IO_file_xsputn __P((_IO_FILE*,const void*,_IO_size_t)); +extern int _IO_file_stat __P((_IO_FILE*, void*)); +extern int _IO_file_close __P((_IO_FILE*)); +extern int _IO_file_underflow __P((_IO_FILE *)); +extern int _IO_file_overflow __P((_IO_FILE *, int)); +#define _IO_file_is_open(__fp) ((__fp)->_fileno >= 0) +extern void _IO_file_init __P((_IO_FILE*)); +extern _IO_FILE* _IO_file_attach __P((_IO_FILE*, int)); +extern _IO_FILE* _IO_file_fopen __P((_IO_FILE*, const char*, const char*)); +extern _IO_ssize_t _IO_file_write __P((_IO_FILE*,const void*,_IO_ssize_t)); +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_fpos_t _IO_file_seek __P((_IO_FILE *, _IO_off_t, int)); +extern void _IO_file_finish __P((_IO_FILE*)); + +/* Other file functions. */ +extern _IO_FILE* _IO_file_attach __P((_IO_FILE *, int)); + +/* Jumptable functions for proc_files. */ +extern _IO_FILE* _IO_proc_open __P((_IO_FILE*, const char*, const char *)); +extern int _IO_proc_close __P((_IO_FILE*)); + +/* Jumptable functions for strfiles. */ +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_fpos_t _IO_str_seekoff __P((_IO_FILE*,_IO_off_t,int,int)); +extern void _IO_str_finish __P ((_IO_FILE*)); + +/* Other strfile functions */ +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*)); + +extern _IO_size_t _IO_getline __P((_IO_FILE*,char*,_IO_size_t,int,int)); +extern _IO_ssize_t _IO_getdelim __P((char**, _IO_size_t*, int, _IO_FILE*)); +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)); +extern int _IO_outfloat __P((double __value, _IO_FILE *__sb, int __type, + int __width, int __precision, int __flags, + int __sign_mode, int __fill)); + +extern _IO_FILE *_IO_list_all; +extern void (*_IO_cleanup_registration_needed) __P ((void)); + +#ifndef EOF +#define EOF (-1) +#endif +#ifndef NULL +#if !defined(__cplusplus) || defined(__GNUC__) +#define NULL ((void*)0) +#else +#define NULL (0) +#endif +#endif + +#define FREE_BUF(_B) free(_B) +#define ALLOC_BUF(_S) (char*)malloc(_S) + +#ifndef OS_FSTAT +#define OS_FSTAT fstat +#endif +struct stat; +extern _IO_ssize_t _IO_read __P((int, void*, _IO_size_t)); +extern _IO_ssize_t _IO_write __P((int, const void*, _IO_size_t)); +extern _IO_off_t _IO_lseek __P((int, _IO_off_t, int)); +extern int _IO_close __P((int)); +extern int _IO_fstat __P((int, struct stat *)); + +/* Operations on _IO_fpos_t. + Normally, these are trivial, but we provide hooks for configurations + where an _IO_fpos_t is a struct. + Note that _IO_off_t must be an integral type. */ + +/* _IO_pos_BAD is an _IO_fpos_t value indicating error, unknown, or EOF. */ +#ifndef _IO_pos_BAD +#define _IO_pos_BAD ((_IO_fpos_t)(-1)) +#endif +/* _IO_pos_as_off converts an _IO_fpos_t value to an _IO_off_t value. */ +#ifndef _IO_pos_as_off +#define _IO_pos_as_off(__pos) ((_IO_off_t)(__pos)) +#endif +/* _IO_pos_adjust adjust an _IO_fpos_t by some number of bytes. */ +#ifndef _IO_pos_adjust +#define _IO_pos_adjust(__pos, __delta) ((__pos) += (__delta)) +#endif +/* _IO_pos_0 is an _IO_fpos_t value indicating beginning of file. */ +#ifndef _IO_pos_0 +#define _IO_pos_0 ((_IO_fpos_t)0) +#endif + +#ifdef __cplusplus +} +#endif + +#if _IO_UNIFIED_JUMPTABLES +#define _IO_FJUMP /* nothing */ +#else +#define _IO_FJUMP &_IO_file_jumps, +#endif +/* check following! */ +#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, _IO_FJUMP FD} + +/* VTABLE_LABEL defines NAME as of the CLASS class. + CNLENGTH is strlen(#CLASS). */ +#ifdef __GNUC__ +#if _G_VTABLE_LABEL_HAS_LENGTH +#define VTABLE_LABEL(NAME, CLASS, CNLENGTH) \ + extern char NAME[] asm (_G_VTABLE_LABEL_PREFIX #CNLENGTH #CLASS); +#else +#define VTABLE_LABEL(NAME, CLASS, CNLENGTH) \ + extern char NAME[] asm (_G_VTABLE_LABEL_PREFIX #CLASS); +#endif +#endif /* __GNUC__ */ + +#if !defined(builtinbuf_vtable) && defined(__cplusplus) +#ifdef __GNUC__ +VTABLE_LABEL(builtinbuf_vtable, builtinbuf, 10) +#else +#if _G_VTABLE_LABEL_HAS_LENGTH +#define builtinbuf_vtable _G_VTABLE_LABEL_PREFIX_ID##10builtinbuf +#else +#define builtinbuf_vtable _G_VTABLE_LABEL_PREFIX_ID##builtinbuf +#endif +#endif +#endif /* !defined(builtinbuf_vtable) && defined(__cplusplus) */ + +#if defined(__STDC__) || defined(__cplusplus) +#define _IO_va_start(args, last) va_start(args, last) +#else +#define _IO_va_start(args, last) va_start(args) +#endif + +extern struct _IO_fake_stdiobuf _IO_stdin_buf, _IO_stdout_buf, _IO_stderr_buf; + +#if 1 +#define COERCE_FILE(FILE) /* Nothing */ +#else +/* This is part of the kludge for binary compatibility with old stdio. */ +#define COERCE_FILE(FILE) \ + (((FILE)->_IO_file_flags & _IO_MAGIC_MASK) == _OLD_MAGIC_MASK \ + && (FILE) = *(FILE**)&((int*)fp)[1]) +#endif + +#ifdef EINVAL +#define MAYBE_SET_EINVAL errno = EINVAL +#else +#define MAYBE_SET_EINVAL /* nothing */ +#endif + +#ifdef DEBUG +#define CHECK_FILE(FILE,RET) \ + if ((FILE) == NULL) { MAYBE_SET_EINVAL; return RET; } \ + else { COERCE_FILE(FILE); \ + if (((FILE)->_IO_file_flags & _IO_MAGIC_MASK) != _IO_MAGIC) \ + { errno = EINVAL; return RET; }} +#else +#define CHECK_FILE(FILE,RET) \ + COERCE_FILE(FILE) +#endif diff --git a/libio/memstream.c b/libio/memstream.c new file mode 100644 index 0000000000..b1cefb0959 --- /dev/null +++ b/libio/memstream.c @@ -0,0 +1,129 @@ +/* Copyright (C) 1995 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 "strfile.h" +#include "libioP.h" +#include <stdlib.h> + + +struct _IO_FILE_memstream +{ + _IO_strfile _sf; + char **bufloc; + _IO_size_t *sizeloc; +}; + + +static int _IO_mem_sync __P ((_IO_FILE* fp)); +static int _IO_mem_close __P ((_IO_FILE* fp)); + + +static const struct _IO_jump_t _IO_mem_jumps = +{ + JUMP_INIT_DUMMY, + JUMP_INIT (finish, _IO_str_finish), + JUMP_INIT (overflow, _IO_str_overflow), + JUMP_INIT (underflow, _IO_str_underflow), + JUMP_INIT (uflow, _IO_default_uflow), + JUMP_INIT (pbackfail, _IO_str_pbackfail), + JUMP_INIT (xsputn, _IO_default_xsputn), + JUMP_INIT (xsgetn, _IO_default_xsgetn), + JUMP_INIT (seekoff, _IO_str_seekoff), + JUMP_INIT (seekpos, _IO_default_seekpos), + JUMP_INIT (setbuf, _IO_default_setbuf), + JUMP_INIT (sync, _IO_mem_sync), + JUMP_INIT (doallocate, _IO_default_doallocate), + JUMP_INIT (read, _IO_default_read), + JUMP_INIT (write, _IO_default_write), + JUMP_INIT (seek, _IO_default_seek), + JUMP_INIT (close, _IO_mem_close), + JUMP_INIT (stat, _IO_default_stat) +}; + +/* 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. */ +_IO_FILE * +open_memstream (bufloc, sizeloc) + char **bufloc; + _IO_size_t *sizeloc; +{ + struct _IO_FILE_memstream *fp; + char *buf; + + fp = (struct _IO_FILE_memstream *) + malloc (sizeof (struct _IO_FILE_memstream)); + if (fp == NULL) + return NULL; + + buf = ALLOC_BUF (_IO_BUFSIZ); + _IO_init (&fp->_sf._f, 0); + _IO_JUMPS (&fp->_sf._f) = &_IO_mem_jumps; + _IO_str_init_static (&fp->_sf._f, buf, _IO_BUFSIZ, buf); + fp->_sf._f._flags &= ~_IO_USER_BUF; + fp->_sf._s._allocate_buffer = (_IO_alloc_type) malloc; + fp->_sf._s._free_buffer = (_IO_free_type) free; + + return &fp->_sf._f; +} + + +static int +_IO_mem_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->_IO_write_ptr == fp->_IO_write_end) + { + _IO_str_overflow (fp, '\0'); + --fp->_IO_write_ptr; + } + else + *fp->_IO_write_ptr = '\0'; + + *mp->bufloc = fp->_IO_buf_base; + *mp->sizeloc = _IO_blen (fp); + + return 0; +} + + +static int _IO_mem_close (fp) + _IO_FILE* fp; +{ + struct _IO_FILE_memstream *mp = (struct _IO_FILE_memstream *) fp; + int res; + + res = _IO_default_close (fp); + if (res < 0) + return res; + + *mp->bufloc = (char *) realloc (fp->_IO_buf_base, _IO_blen (fp) + 1); + if (*mp->bufloc == NULL) + return -1; + (*mp->bufloc)[_IO_blen (fp)] = '\0'; + *mp->sizeloc = _IO_blen (fp); + + return 0; +} diff --git a/libio/putc.c b/libio/putc.c new file mode 100644 index 0000000000..675fe5eedf --- /dev/null +++ b/libio/putc.c @@ -0,0 +1,30 @@ +/* Copyright (C) 1991, 1995 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., 675 Mass Ave, +Cambridge, MA 02139, USA. */ + +#include "libioP.h" +#include "stdio.h" + +#undef putc + +int +putc (c, stream) + int c; + _IO_FILE *stream; +{ + return _IO_putc (c, stream); +} diff --git a/libio/putchar.c b/libio/putchar.c new file mode 100644 index 0000000000..bf10da9468 --- /dev/null +++ b/libio/putchar.c @@ -0,0 +1,29 @@ +/* Copyright (C) 1991, 1995 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., 675 Mass Ave, +Cambridge, MA 02139, USA. */ + +#include "libioP.h" +#include "stdio.h" + +#undef putchar + +int +putchar (c) + int c; +{ + return _IO_putc (c, stdout); +} diff --git a/libio/rewind.c b/libio/rewind.c new file mode 100644 index 0000000000..dfb02cc3f2 --- /dev/null +++ b/libio/rewind.c @@ -0,0 +1,33 @@ +/* Copyright (C) 1993 Free Software Foundation + +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 "stdio.h" +#include "libioP.h" + +void +rewind (fp) + _IO_FILE* fp; +{ + CHECK_FILE (fp, ); + _IO_rewind (fp); +} diff --git a/libio/setbuf.c b/libio/setbuf.c new file mode 100644 index 0000000000..f3518aadad --- /dev/null +++ b/libio/setbuf.c @@ -0,0 +1,33 @@ +/* Copyright (C) 1993 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" + +void +setbuf (fp, buf) + _IO_FILE *fp; + char *buf; +{ + _IO_setbuffer (fp, buf, _IO_BUFSIZ); +} diff --git a/libio/setlinebuf.c b/libio/setlinebuf.c new file mode 100644 index 0000000000..b456d5846c --- /dev/null +++ b/libio/setlinebuf.c @@ -0,0 +1,35 @@ +/* +Copyright (C) 1993 Free Software Foundation + +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 setlinebuf + +void +setlinebuf (stream) + _IO_FILE *stream; +{ + _IO_setvbuf (stream, NULL, 1, 0); +} diff --git a/libio/stdfiles.c b/libio/stdfiles.c new file mode 100644 index 0000000000..1d0ef85be9 --- /dev/null +++ b/libio/stdfiles.c @@ -0,0 +1,44 @@ +/* +Copyright (C) 1993, 1994 Free Software Foundation + +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. */ + + +/* This file provides definitions of _IO_stdin, _IO_stdout, and _IO_stderr + for C code. Compare stdstreams.cc. + (The difference is that here the vtable field is set to 0, + so the objects defined are not valid C++ objects. On the other + hand, we don't need a C++ compiler to build this file.) */ + +#include "libioP.h" + + +#define DEF_STDFILE(NAME, FD, CHAIN, FLAGS) \ + struct _IO_FILE_plus NAME \ + = {FILEBUF_LITERAL(CHAIN, FLAGS, FD), &_IO_file_jumps} + +DEF_STDFILE(_IO_stdin_, 0, 0, _IO_NO_WRITES); +DEF_STDFILE(_IO_stdout_, 1, &_IO_stdin_.file, _IO_NO_READS); +DEF_STDFILE(_IO_stderr_, 2, &_IO_stdout_.file, + _IO_NO_READS+_IO_UNBUFFERED); + +_IO_FILE *_IO_list_all = &_IO_stderr_.file; diff --git a/libio/stdio.c b/libio/stdio.c new file mode 100644 index 0000000000..cd56dba307 --- /dev/null +++ b/libio/stdio.c @@ -0,0 +1,12 @@ +#include "libioP.h" +#include "stdio.h" + +/* Define non-macro versions of stdin/stdout/stderr, + * for use by debuggers. */ + +#undef stdin +#undef stdout +#undef stderr +FILE* stdin = &_IO_stdin_.file; +FILE* stdout = &_IO_stdout_.file; +FILE* stderr = &_IO_stderr_.file; diff --git a/libio/stdio.h b/libio/stdio.h new file mode 100644 index 0000000000..893e7bf3fe --- /dev/null +++ b/libio/stdio.h @@ -0,0 +1,196 @@ +/* This is part of the iostream/stdio library, providing -*- C -*- I/O. + Define ANSI C stdio on top of C++ iostreams. + Copyright (C) 1991, 1994, 1995 Free Software Foundation, Inc. + +This 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. + + +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 +Library General Public License for more details. + +You should have received a copy of the GNU Library General Public +License along with this library; if not, write to the Free Software +Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. +*/ + +/* + * ANSI Standard: 4.9 INPUT/OUTPUT <stdio.h> + */ + +#ifndef _STDIO_H +#define _STDIO_H +#define _STDIO_USES_IOSTREAM + +#include <libio.h> + +#ifndef NULL +#ifdef __cplusplus +#define NULL 0 +#else +#define NULL (void*)0 +#endif +#endif + +#ifndef EOF +#define EOF (-1) +#endif +#ifndef BUFSIZ +#define BUFSIZ 1024 +#endif + +#define _IOFBF 0 /* Fully buffered. */ +#define _IOLBF 1 /* Line buffered. */ +#define _IONBF 2 /* No buffering. */ + +#define SEEK_SET 0 +#define SEEK_CUR 1 +#define SEEK_END 2 + + /* define size_t. Crud in case <sys/types.h> has defined it. */ +#if !defined(_SIZE_T) && !defined(_T_SIZE_) && !defined(_T_SIZE) +#if !defined(__SIZE_T) && !defined(_SIZE_T_) && !defined(___int_size_t_h) +#if !defined(_GCC_SIZE_T) && !defined(_SIZET_) +#define _SIZE_T +#define _T_SIZE_ +#define _T_SIZE +#define __SIZE_T +#define _SIZE_T_ +#define ___int_size_t_h +#define _GCC_SIZE_T +#define _SIZET_ +typedef _IO_size_t size_t; +#endif +#endif +#endif + +typedef struct _IO_FILE FILE; +typedef _IO_fpos_t fpos_t; + +#define FOPEN_MAX _G_FOPEN_MAX +#define FILENAME_MAX _G_FILENAME_MAX +#define TMP_MAX 999 /* Only limited by filename length */ + +#define L_ctermid 9 +#define L_cuserid 9 +#define P_tmpdir "/tmp" +#define L_tmpnam 20 + +/* For use by debuggers. These are linked in if printf or fprintf are used. */ +extern FILE *stdin, *stdout, *stderr; /* TODO */ + +#define stdin _IO_stdin +#define stdout _IO_stdout +#define stderr _IO_stderr + +#ifdef __cplusplus +extern "C" { +#endif + +#ifndef __P +#if defined(__STDC__) || defined(__cplusplus) || defined(c_plusplus) +#define __P(args) args +#else +#define __P(args) () +#endif +#endif /*!__P*/ + +extern void clearerr __P ((FILE*)); +extern int fclose __P ((FILE*)); +extern int feof __P ((FILE*)); +extern int ferror __P ((FILE*)); +extern int fflush __P ((FILE*)); +extern int fgetc __P ((FILE *)); +extern int fgetpos __P ((FILE* fp, fpos_t *pos)); +extern char* fgets __P ((char*, int, FILE*)); +extern FILE* fopen __P ((__const char*, __const char*)); +extern int fprintf __P ((FILE*, __const char* format, ...)); +extern int fputc __P ((int, FILE*)); +extern int fputs __P ((__const char *str, FILE *fp)); +extern size_t fread __P ((void*, size_t, size_t, FILE*)); +extern FILE* freopen __P ((__const char*, __const char*, FILE*)); +extern int fscanf __P ((FILE *fp, __const char* format, ...)); +extern int fseek __P ((FILE* fp, long int offset, int whence)); +extern int fsetpos __P ((FILE* fp, __const fpos_t *pos)); +extern long int ftell __P ((FILE* fp)); +extern size_t fwrite __P ((__const void*, size_t, size_t, FILE*)); +extern int getc __P ((FILE *)); +extern int getchar __P ((void)); +extern char* gets __P ((char*)); +extern void perror __P ((__const char *)); +extern int printf __P ((__const char* format, ...)); +extern int putc __P ((int, FILE *)); +extern int putchar __P ((int)); +extern int puts __P ((__const char *str)); +extern int remove __P ((__const char*)); +extern int rename __P ((__const char* _old, __const char* _new)); +extern void rewind __P ((FILE*)); +extern int scanf __P ((__const char* format, ...)); +extern void setbuf __P ((FILE*, char*)); +extern void setlinebuf __P ((FILE*)); +extern void setbuffer __P ((FILE*, char*, int)); +extern int setvbuf __P ((FILE*, char*, int mode, size_t size)); +extern int sprintf __P ((char*, __const char* format, ...)); +extern int sscanf __P ((__const char* string, __const char* format, ...)); +extern FILE* tmpfile __P ((void)); +extern char* tmpnam __P ((char*)); +extern int ungetc __P ((int c, FILE* fp)); +extern int vfprintf __P ((FILE *fp, char __const *fmt0, _G_va_list)); +extern int vprintf __P ((char __const *fmt, _G_va_list)); +extern int vsprintf __P ((char* string, __const char* format, _G_va_list)); + +#ifndef __STRICT_ANSI__ +extern int dprintf __P ((int, __const char *, ...)); +extern int vdprintf __P ((int, __const char *, _G_va_list)); +extern int vfscanf __P ((FILE*, __const char *, _G_va_list)); +extern int vscanf __P ((__const char *, _G_va_list)); +extern int vsscanf __P ((__const char *, __const char *, _G_va_list)); +#endif + +#if !defined(__STRICT_ANSI__) || defined(_POSIX_SOURCE) +extern FILE *fdopen __P ((int, __const char *)); +extern int fileno __P ((FILE*)); +extern FILE* popen __P ((__const char*, __const char*)); +extern int pclose __P ((FILE*)); +#endif + +#ifdef __USE_GNU +extern _IO_ssize_t getdelim __P ((char **, size_t *, int, FILE*)); +extern _IO_ssize_t getline __P ((char **, size_t *, FILE *)); + +extern int snprintf __P ((char *, size_t, __const char *, ...)); +extern int __snprintf __P ((char *, size_t, __const char *, ...)); +extern int vsnprintf __P ((char *, size_t, __const char *, _G_va_list)); + +/* 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. */ +extern FILE *open_memstream __P ((char **__bufloc, size_t *__sizeloc)); +#endif + +extern int __underflow __P ((struct _IO_FILE*)); +extern int __overflow __P ((struct _IO_FILE*, int)); + +#define getc(fp) _IO_getc (fp) +#define putc(c, fp) _IO_putc (c, fp) +#define putchar(c) putc (c, stdout) +#define getchar() getc (stdin) + +#ifdef __USE_BSD +extern int sys_nerr; +extern const char *const sys_errlist[]; +#endif +#ifdef __USE_GNU +extern int _sys_nerr; +extern const char *const _sys_errlist[]; +#endif + +#ifdef __cplusplus +} +#endif + +#endif /* !_STDIO_H */ diff --git a/libio/strfile.h b/libio/strfile.h new file mode 100644 index 0000000000..55783bb5c1 --- /dev/null +++ b/libio/strfile.h @@ -0,0 +1,46 @@ +/* +Copyright (C) 1993 Free Software Foundation + +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 <libio.h> +#ifdef TODO +Merge into libio.h ? +#endif + +typedef void *(*_IO_alloc_type) __P((_IO_size_t)); +typedef void (*_IO_free_type) __P((void*)); + +struct _IO_str_fields +{ + /* The current length is max(_len, _IO_write_ptr-_IO_write_base). */ + _IO_size_t _len; + _IO_alloc_type _allocate_buffer; + _IO_free_type _free_buffer; +}; + +typedef struct _IO_strfile_ +{ + struct _IO_FILE _f; + const void *_vtable; + struct _IO_str_fields _s; +} _IO_strfile; diff --git a/libio/strops.c b/libio/strops.c new file mode 100644 index 0000000000..f4f45259fb --- /dev/null +++ b/libio/strops.c @@ -0,0 +1,285 @@ +/* +Copyright (C) 1993 Free Software Foundation + +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> + +#define LEN(fp) (((_IO_strfile*)(fp))->_s._len) + +#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 +DEFUN(_IO_str_init_static, (fp, ptr, size, pstart), + _IO_FILE *fp AND char *ptr AND int size AND char *pstart) +{ + if (size == 0) + size = strlen(ptr); + else if (size < 0) + { + /* If size is negative 'the characters are assumed to + continue indefinitely.' This is kind of messy ... */ +#if 1 + int s; + size = 512; + /* Try increasing powers of 2, as long as we don't wrap around. + This can lose in pathological cases (ptr near the end + of the address space). A better solution might be to + adjust the size on underflow/overflow. FIXME. */ + for (s; s = 2*size, s > 0 && ptr + s > ptr && s < 0x4000000L; ) + size = s; + size = s; +#else + /* The following semi-portable kludge assumes that + sizeof(unsigned long) == sizeof(char*). Hence, + (unsigned long)(-1) should be the largest possible address. */ + unsigned long highest = (unsigned long)(-1); + /* Pointers are signed on some brain-damaged systems, in + which case we divide by two to get the maximum signed address. */ + if ((char*)highest < ptr) + highest >>= 1; + size = (char*)highest - ptr; +#endif + } + _IO_setb(fp, ptr, ptr+size, 0); + + fp->_IO_write_base = ptr; + fp->_IO_read_base = ptr; + fp->_IO_read_ptr = ptr; + if (pstart) + { + fp->_IO_write_ptr = pstart; + fp->_IO_write_end = ptr+size; + fp->_IO_read_end = pstart; + } + else + { + fp->_IO_write_ptr = ptr; + fp->_IO_write_end = ptr; + fp->_IO_read_end = ptr+size; + } + LEN(fp) = size; + /* A null _allocate_buffer function flags the strfile as being static. */ + (((_IO_strfile*)(fp))->_s._allocate_buffer) = (_IO_alloc_type)0; +} + +void +DEFUN(_IO_str_init_readonly, (fp, ptr, size), + _IO_FILE *fp AND const char *ptr AND int size) +{ + _IO_str_init_static (fp, (char*)ptr, size, NULL); + fp->_IO_file_flags |= _IO_NO_WRITES; +} + +int +DEFUN(_IO_str_overflow, (fp, c), + register _IO_FILE* fp AND int c) +{ + int flush_only = c == EOF; + _IO_size_t pos = fp->_IO_write_ptr - fp->_IO_write_base; + _IO_size_t get_pos = fp->_IO_read_ptr - fp->_IO_read_base; + if (fp->_flags & _IO_NO_WRITES) + return flush_only ? 0 : EOF; + if (pos > LEN(fp)) LEN(fp) = pos; + if ((fp->_flags & _IO_TIED_PUT_GET) && !(fp->_flags & _IO_CURRENTLY_PUTTING)) + { + pos = get_pos; + fp->_flags |= _IO_CURRENTLY_PUTTING; + get_pos = LEN(fp); + } + if (pos >= _IO_blen(fp) + flush_only) + { + if (fp->_flags & _IO_USER_BUF) /* not allowed to enlarge */ + { +#ifdef TODO + if (indefinite size) + { + fp->_IO_buf_end += 512; + } + else +#endif + return EOF; + } + else + { + char *new_buf; + _IO_size_t new_size = 2 * _IO_blen(fp); + new_buf + = (char*)(*((_IO_strfile*)fp)->_s._allocate_buffer)(new_size); + if (new_buf == NULL) + { + /* __ferror(fp) = 1; */ + return EOF; + } + memcpy(new_buf, fp->_IO_buf_base, _IO_blen(fp)); +#if 0 + if (lenp == &LEN(fp)) /* use '\0'-filling */ + memset(new_buf + pos, 0, blen() - pos); +#endif + if (fp->_IO_buf_base) + { + (*((_IO_strfile*)fp)->_s._free_buffer)(fp->_IO_buf_base); + /* Make sure _IO_setb won't try to delete _IO_buf_base. */ + fp->_IO_buf_base = NULL; + } + _IO_setb(fp, new_buf, new_buf + new_size, 1); + fp->_IO_write_base = new_buf; + } + fp->_IO_write_end = fp->_IO_buf_end; + } + + fp->_IO_write_ptr = fp->_IO_buf_base + pos; + + fp->_IO_read_base = fp->_IO_buf_base; + fp->_IO_read_ptr = fp->_IO_buf_base + get_pos; + fp->_IO_read_end = fp->_IO_buf_base + LEN(fp); + + if (!flush_only) + *fp->_IO_write_ptr++ = (unsigned char) c; + return c; +} + +int +DEFUN(_IO_str_underflow, (fp), + register _IO_FILE* fp) +{ + _IO_size_t ppos = fp->_IO_write_ptr - fp->_IO_write_base; + if (ppos > LEN(fp)) LEN(fp) = ppos; + if ((fp->_flags & _IO_TIED_PUT_GET) && (fp->_flags & _IO_CURRENTLY_PUTTING)) + { + fp->_flags &= ~_IO_CURRENTLY_PUTTING; + fp->_IO_write_ptr = fp->_IO_write_end; + } + fp->_IO_read_end = fp->_IO_read_base + LEN(fp); + if (fp->_IO_read_ptr < fp->_IO_read_end) + return *fp->_IO_read_ptr; + else + return EOF; +} + +_IO_ssize_t +DEFUN(_IO_str_count, (fp), + register _IO_FILE *fp) +{ + _IO_ssize_t put_len = fp->_IO_write_ptr - fp->_IO_write_base; + if (put_len < LEN(fp)) + put_len = LEN(fp); + return put_len; +} + +_IO_pos_t +DEFUN(_IO_str_seekoff, (fp, offset, dir, mode), + register _IO_FILE *fp AND _IO_off_t offset AND int dir AND int mode) +{ + _IO_ssize_t cur_size = _IO_str_count(fp); + _IO_pos_t 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->_IO_read_ptr - fp->_IO_read_base; + break; + default: /* case _IO_seek_set: */ + break; + } + if (offset < 0 || (_IO_size_t)offset > cur_size) + return EOF; + fp->_IO_read_ptr = fp->_IO_read_base + offset; + fp->_IO_read_end = fp->_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->_IO_write_ptr - fp->_IO_write_base; + break; + default: /* case _IO_seek_set: */ + break; + } + if (offset < 0 || (_IO_size_t)offset > cur_size) + return EOF; + LEN(fp) = cur_size; + fp->_IO_write_ptr = fp->_IO_write_base + offset; + new_pos = offset; + } + return new_pos; +} + +int +DEFUN(_IO_str_pbackfail, (fp, c), + register _IO_FILE *fp AND int c) +{ + if ((fp->_flags & _IO_NO_WRITES) && c != EOF) + return EOF; + return _IO_default_pbackfail(fp, c); +} + +void +DEFUN (_IO_str_finish, (fp), + register _IO_FILE* fp) +{ + if (fp->_IO_buf_base && !(fp->_flags & _IO_USER_BUF)) + (((_IO_strfile*)fp)->_s._free_buffer)(fp->_IO_buf_base); + fp->_IO_buf_base = NULL; + + _IO_default_finish(fp); +} + +struct _IO_jump_t _IO_str_jumps = { + JUMP_INIT_DUMMY, + JUMP_INIT(finish, _IO_str_finish), + JUMP_INIT(overflow, _IO_str_overflow), + JUMP_INIT(underflow, _IO_str_underflow), + JUMP_INIT(uflow, _IO_default_uflow), + JUMP_INIT(pbackfail, _IO_str_pbackfail), + JUMP_INIT(xsputn, _IO_default_xsputn), + JUMP_INIT(xsgetn, _IO_default_xsgetn), + JUMP_INIT(seekoff, _IO_str_seekoff), + JUMP_INIT(seekpos, _IO_default_seekpos), + JUMP_INIT(setbuf, _IO_default_setbuf), + JUMP_INIT(sync, _IO_default_sync), + JUMP_INIT(doallocate, _IO_default_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) +}; diff --git a/libio/vasprintf.c b/libio/vasprintf.c new file mode 100644 index 0000000000..ee92f83b1c --- /dev/null +++ b/libio/vasprintf.c @@ -0,0 +1,61 @@ +/* +Copyright (C) 1995 Free Software Foundation + +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 GNU CC; see the file COPYING. If not, write to +the Free Software Foundation, 675 Mass Ave, Cambridge, MA 02139, 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 <malloc.h> +#include "libioP.h" +#include "stdio.h" +#include "strfile.h" + +int +_IO_vasprintf (result_ptr, format, args) + char **result_ptr; + const char *format; + _IO_va_list args; +{ + /* Initial size of the buffer to be used. Will be doubled each time an + overflow occurs. */ + const _IO_size_t init_string_size = 100; + char *string; + _IO_strfile sf; + int ret; + string = ALLOC_BUF(init_string_size); + if (string == NULL) + return -1; + _IO_init((_IO_FILE*)&sf, 0); + _IO_JUMPS((_IO_FILE*)&sf) = &_IO_str_jumps; + _IO_str_init_static ((_IO_FILE*)&sf, string, init_string_size, string); + sf._f._flags &= ~_IO_USER_BUF; + sf._s._allocate_buffer = (_IO_alloc_type)malloc; + sf._s._free_buffer = (_IO_free_type)free; + ret = _IO_vfprintf((_IO_FILE*)&sf, format, args); + if (ret < 0) + return ret; + *result_ptr = (char*)realloc(sf._f._IO_buf_base, + (sf._f._IO_write_ptr - sf._f._IO_write_base) +1); + if (*result_ptr == NULL) + *result_ptr = sf._f._IO_buf_base; + (*result_ptr)[sf._f._IO_write_ptr-sf._f._IO_write_base] = '\0'; + return ret; +} +weak_alias (_IO_vasprintf, vasprintf) diff --git a/libio/vdprintf.c b/libio/vdprintf.c new file mode 100644 index 0000000000..b92251eada --- /dev/null +++ b/libio/vdprintf.c @@ -0,0 +1,60 @@ +/* +Copyright (C) 1995 Free Software Foundation + +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 "libio.h" + +int +_IO_vdprintf (d, format, arg) + int d; + const char *format; + _IO_va_list arg; +{ + struct _IO_FILE_plus tmpfil; + int done; + + _IO_init (&tmpfil.file, 0); + _IO_JUMPS (&tmpfil.file) = &_IO_file_jumps; + _IO_file_init (&tmpfil.file); +#if !_IO_UNIFIED_JUMPTABLES + tmpfil.vtable = NULL; +#endif + if (_IO_file_attach (&tmpfil.file, d) == NULL) + { + _IO_un_link (&tmpfil.file); + return EOF; + } + tmpfil.file._flags &= ~_IO_DELETE_DONT_CLOSE; + + tmpfil.file._IO_file_flags = + _IO_mask_flags (&tmpfil.file, _IO_NO_READS, + _IO_NO_READS+_IO_NO_WRITES+_IO_IS_APPENDING); + + done = _IO_vfprintf (&tmpfil.file, format, arg); + + _IO_FINISH (&tmpfil.file); + + return done; +} +weak_alias (_IO_vdprintf, vdprintf) diff --git a/libio/vscanf.c b/libio/vscanf.c new file mode 100644 index 0000000000..f905cff5a3 --- /dev/null +++ b/libio/vscanf.c @@ -0,0 +1,37 @@ +/* +Copyright (C) 1993 Free Software Foundation + +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 vscanf + +int +_IO_vscanf (format, args) + const char *format; + _IO_va_list args; +{ + return _IO_vfscanf (_IO_stdin, format, args, NULL); +} +weak_alias (_IO_vscanf, vscanf) diff --git a/libio/vsnprintf.c b/libio/vsnprintf.c new file mode 100644 index 0000000000..a04da8242a --- /dev/null +++ b/libio/vsnprintf.c @@ -0,0 +1,44 @@ +/* +Copyright (C) 1994 Free Software Foundation + +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" + +int +_IO_vsnprintf (string, maxlen, format, args) + char *string; + _IO_size_t maxlen; + const char *format; + _IO_va_list args; +{ + _IO_strfile sf; + int ret; + _IO_init ((_IO_FILE *) &sf, 0); + _IO_JUMPS ((_IO_FILE *) &sf) = &_IO_str_jumps; + _IO_str_init_static ((_IO_FILE *) &sf, string, maxlen - 1, string); + ret = _IO_vfprintf ((_IO_FILE *) &sf, format, args); + *((_IO_FILE *) &sf)->_IO_write_ptr = '\0'; + return ret; +} +weak_alias (_IO_vsnprintf, vsnprintf) diff --git a/stdio-common/getline.c b/stdio-common/getline.c index 1a2f975c75..f103979333 100644 --- a/stdio-common/getline.c +++ b/stdio-common/getline.c @@ -22,6 +22,11 @@ Cambridge, MA 02139, USA. */ #undef __getline +#ifdef USE_IN_LIBIO +# define ssize_t _IO_ssize_t +# define __getdelim _IO_getdelim +#endif + /* Like getdelim, but always looks for a newline. */ ssize_t DEFUN(__getline, (lineptr, n, stream), diff --git a/stdio-common/printf_fp.c b/stdio-common/printf_fp.c index 28d13d61b8..31c009e891 100644 --- a/stdio-common/printf_fp.c +++ b/stdio-common/printf_fp.c @@ -269,7 +269,7 @@ __printf_fp (fp, info, args) { fracsize = __mpn_extract_long_double (fp_input, (sizeof (fp_input) / - sizeof (fp_input[0])), + sizeof (fp_input[0])), &exponent, &is_neg, fpnum.ldbl); to_shift = 1 + fracsize * BITS_PER_MP_LIMB - LDBL_MANT_DIG; @@ -496,7 +496,7 @@ __printf_fp (fp, info, args) /* Now shift the input value to its right place. */ cy = __mpn_lshift (frac, fp_input, fracsize, to_shift); - frac[fracsize++] = cy; + frac[fracsize++] = cy; assert (cy == 1 || (frac[fracsize - 2] == 0 && frac[0] == 0)); expsign = 1; @@ -524,7 +524,7 @@ __printf_fp (fp, info, args) if (cy == 0) --tmpsize; - count_leading_zeros (cnt_h, tmp[tmpsize - 1]); + count_leading_zeros (cnt_h, tmp[tmpsize - 1]); incr = (tmpsize - fracsize) * BITS_PER_MP_LIMB + BITS_PER_MP_LIMB - 1 - cnt_h; @@ -559,7 +559,7 @@ __printf_fp (fp, info, args) && tmp[tmpsize - 2] < topval[0])))) { /* The factor is right. Adapt binary and decimal - exponents. */ + exponents. */ exponent -= incr; exp10 |= 1 << explog; @@ -639,7 +639,7 @@ __printf_fp (fp, info, args) /* Now shift the input value to its right place. */ cy = __mpn_lshift (frac, fp_input, fracsize, (exponent + to_shift)); - frac[fracsize++] = cy; + frac[fracsize++] = cy; exponent = 0; } @@ -714,7 +714,7 @@ __printf_fp (fp, info, args) it is possible that we need two more characters in front of all the other output. */ buffer = alloca (2 + chars_needed); - cp = startp = buffer + 2; /* Let room for rounding. */ + cp = startp = buffer + 2; /* Let room for rounding. */ /* Do the real work: put digits in allocated buffer. */ if (expsign == 0 || type != 'f') @@ -886,7 +886,7 @@ __printf_fp (fp, info, args) } /* Compute number of characters which must be filled with the padding - character. */ + character. */ if (is_neg || info->showsign || info->space) --width; width -= cp - startp; diff --git a/stdio-common/snprintf.c b/stdio-common/snprintf.c index a7a6e722ee..ca0b60aed6 100644 --- a/stdio-common/snprintf.c +++ b/stdio-common/snprintf.c @@ -20,6 +20,7 @@ Cambridge, MA 02139, USA. */ #include <stdio.h> #ifdef USE_IN_LIBIO +# include <libioP.h> # define __vsnprintf _IO_vsnprintf #endif diff --git a/stdio-common/vfprintf.c b/stdio-common/vfprintf.c index e22403be22..9e855ded56 100644 --- a/stdio-common/vfprintf.c +++ b/stdio-common/vfprintf.c @@ -239,11 +239,11 @@ vfprintf (s, format, ap) /* Fill in the types of all the arguments. */ for (cnt = 0; cnt < nspecs; ++cnt) { - /* If the width is determined by an argument this is an int. */ + /* If the width is determined by an argument this is an int. */ if (specs[cnt].width_arg != -1) args_type[specs[cnt].width_arg] = PA_INT; - /* If the precision is determined by an argument this is an int. */ + /* If the precision is determined by an argument this is an int. */ if (specs[cnt].prec_arg != -1) args_type[specs[cnt].prec_arg] = PA_INT; @@ -583,16 +583,16 @@ vfprintf (s, format, ap) case 'n': /* Answer the count of characters written. */ if (specs[cnt].info.is_longlong) - *(long long int *) + *(long long int *) args_value[specs[cnt].data_arg].pa_pointer = done; else if (specs[cnt].info.is_long) - *(long int *) + *(long int *) args_value[specs[cnt].data_arg].pa_pointer = done; else if (!specs[cnt].info.is_short) - *(int *) + *(int *) args_value[specs[cnt].data_arg].pa_pointer = done; else - *(short int *) + *(short int *) args_value[specs[cnt].data_arg].pa_pointer = done; break; @@ -745,23 +745,24 @@ _IO_helper_overflow (s, c) static const struct _IO_jump_t _IO_helper_jumps = { - _IO_helper_overflow, - _IO_default_underflow, - _IO_default_xsputn, - _IO_default_xsgetn, - _IO_default_read, - _IO_default_write, - _IO_default_doallocate, - _IO_default_pbackfail, - _IO_default_setbuf, - _IO_default_sync, - _IO_default_finish, - _IO_default_close, - _IO_default_stat, - _IO_default_seek, - _IO_default_seekoff, - _IO_default_seekpos, - _IO_default_uflow + JUMP_INIT_DUMMY, + JUMP_INIT (finish, _IO_default_finish), + JUMP_INIT (overflow, _IO_helper_overflow), + JUMP_INIT (underflow, _IO_default_underflow), + JUMP_INIT (uflow, _IO_default_uflow), + JUMP_INIT (pbackfail, _IO_default_pbackfail), + JUMP_INIT (xsputn, _IO_default_xsputn), + JUMP_INIT (xsgetn, _IO_default_xsgetn), + JUMP_INIT (seekoff, _IO_default_seekoff), + JUMP_INIT (seekpos, _IO_default_seekpos), + JUMP_INIT (setbuf, _IO_default_setbuf), + JUMP_INIT (sync, _IO_default_sync), + JUMP_INIT (doallocate, _IO_default_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) }; static int @@ -781,8 +782,8 @@ buffered_vfprintf (s, format, args) hp->_IO_write_ptr = buf; hp->_IO_write_end = buf + sizeof buf; hp->_IO_file_flags = _IO_MAGIC|_IO_NO_READS; - hp->_jumps = (struct _IO_jump_t *) &_IO_helper_jumps; - + _IO_JUMPS (hp) = (struct _IO_jump_t *) &_IO_helper_jumps; + /* Now print to helper instead. */ result = _IO_vfprintf (hp, format, args); diff --git a/stdio-common/vfscanf.c b/stdio-common/vfscanf.c index a778346287..a3c058495e 100644 --- a/stdio-common/vfscanf.c +++ b/stdio-common/vfscanf.c @@ -34,23 +34,79 @@ Cambridge, MA 02139, USA. */ #define LONGLONG long #endif - -#define inchar() ((c = getc(s)) == EOF ? EOF : (++read_in, c)) -#define conv_error() return (ungetc(c, s), done) -#define input_error() return (done == 0 ? EOF : done) -#define memory_error() return ((errno = ENOMEM), EOF) +#ifdef USE_IN_LIBIO +# include <libioP.h> +# include <libio.h> + +/* Those are flags in the conversion format. */ +# define LONG 0x01 /* l: long or double */ +# define LONGDBL 0x02 /* L: long long or long double */ +# define SHORT 0x04 /* h: short */ +# define SUPPRESS 0x08 /* suppress assignment */ +# define POINTER 0x10 /* weird %p pointer (`fake hex') */ +# define NOSKIP 0x20 /* do not skip blanks */ +# define WIDTH 0x40 /* width */ + + +# define va_list _IO_va_list +# define ungetc(c, s) _IO_ungetc (c, s) +# define inchar() ((c = _IO_getc(s)), ++read_in, c) +# define conv_error() return ((errp != NULL && (*errp |= 2)), \ + (c == EOF || _IO_ungetc(c, s)), done) + +# define input_error() return ((errp != NULL && (*errp |= 1)), \ + done == 0 ? EOF : done) +# define memory_error() return ((errno = ENOMEM), EOF) +# define ARGCHECK(s, format) \ + do \ + { \ + /* Check file argument for consistence. */ \ + CHECK_FILE (s, -1); \ + if (s->_flags & _IO_NO_READS || format == NULL) \ + { \ + MAYBE_SET_EINVAL; \ + return -1; \ + } \ + } while (0) +#else +# define inchar() ((c = getc(s)) == EOF ? EOF : (++read_in, c)) +# define conv_error() return (ungetc(c, s), done) +# define input_error() return (done == 0 ? EOF : done) +# define memory_error() return ((errno = ENOMEM), EOF) +# define ARGCHECK(s, format) \ + do \ + { \ + /* Check file argument for consistence. */ \ + if (!__validfp (s) || !s->__mode.__read || format == NULL) \ + { \ + errno = EINVAL; \ + return -1; \ + } \ + } while (0) +#endif /* Read formatted input from S according to the format string FORMAT, using the argument list in ARG. Return the number of assignments made, or -1 for an input error. */ +#ifdef USE_IN_LIBIO int -DEFUN(__vfscanf, (s, format, arg), - FILE *s AND CONST char *format AND va_list argptr) +_IO_vfscanf (s, format, argptr, errp) + _IO_FILE *s; + const char *format; + _IO_va_list argptr; + int *errp; +#else +int +__vfscanf (s, format, arg) + FILE *s; + const char *format; + va_list argptr; +#endif { va_list arg = (va_list) argptr; - register CONST char *f = format; + register const char *f = format; register char fc; /* Current character of the format. */ register size_t done = 0; /* Assignments done. */ register size_t read_in = 0; /* Chars read in. */ @@ -58,14 +114,17 @@ DEFUN(__vfscanf, (s, format, arg), register int do_assign; /* Whether to do an assignment. */ register int width; /* Maximum field width. */ int group_flag; /* %' modifier flag. */ +#ifdef USE_IN_LIBIO + int flags; /* Trace flags for current format element. */ +#endif /* Type modifiers. */ int is_short, is_long, is_long_double; #ifdef HAVE_LONGLONG /* We use the `L' modifier for `long long int'. */ -#define is_longlong is_long_double +# define is_longlong is_long_double #else -#define is_longlong 0 +# define is_longlong 0 #endif int malloc_string; /* Args are char ** to be filled in. */ /* Status for reading F-P nums. */ @@ -92,18 +151,14 @@ DEFUN(__vfscanf, (s, format, arg), char *w; /* Pointer into WORK. */ wchar_t decimal; /* Decimal point character. */ - if (!__validfp(s) || !s->__mode.__read || format == NULL) - { - errno = EINVAL; - return EOF; - } + ARGCHECK (s, format); /* Figure out the decimal point character. */ if (mbtowc (&decimal, _NL_CURRENT (LC_NUMERIC, DECIMAL_POINT), strlen (_NL_CURRENT (LC_NUMERIC, DECIMAL_POINT))) <= 0) decimal = (wchar_t) *_NL_CURRENT (LC_NUMERIC, DECIMAL_POINT); - c = inchar(); + c = inchar (); /* Run through the format string. */ while (*f != '\0') @@ -112,27 +167,38 @@ DEFUN(__vfscanf, (s, format, arg), /* Extract the next argument, which is of type TYPE. For a %N$... spec, this is the Nth argument from the beginning; otherwise it is the next argument after the state now in ARG. */ -#define ARG(type) (argpos == 0 ? va_arg (arg, type) : \ +#if 0 + /* XXX Possible optimization. */ +# define ARG(type) (argpos == 0 ? va_arg (arg, type) : \ + ({ va_list arg = (va_list) argptr; \ + arg = (va_list) ((char *) arg \ + + (argpos - 1) \ + * __va_rounded_size (void *)); \ + va_arg (arg, type); \ + })) +#else +# define ARG(type) (argpos == 0 ? va_arg (arg, type) : \ ({ unsigned int pos = argpos; \ va_list arg = (va_list) argptr; \ while (--pos > 0) \ (void) va_arg (arg, void *); \ va_arg (arg, type); \ })) +#endif if (!isascii (*f)) { /* Non-ASCII, may be a multibyte. */ - int len = mblen (f, strlen(f)); + int len = mblen (f, strlen (f)); if (len > 0) { while (len-- > 0) if (c == EOF) - input_error(); + input_error (); else if (c == *f++) - (void) inchar(); + (void) inchar (); else - conv_error(); + conv_error (); continue; } } @@ -142,8 +208,8 @@ DEFUN(__vfscanf, (s, format, arg), { /* Characters other than format specs must just match. */ if (c == EOF) - input_error(); - if (isspace(fc)) + input_error (); + if (isspace (fc)) { /* Whitespace characters match any amount of whitespace. */ while (isspace (c)) @@ -151,12 +217,17 @@ DEFUN(__vfscanf, (s, format, arg), continue; } else if (c == fc) - (void) inchar(); + (void) inchar (); else - conv_error(); + conv_error (); continue; } +#ifdef USE_IN_LIBIO + /* That is the start of the coversion string. */ + flags = 0; +#endif + /* Initialize state of modifiers. */ argpos = 0; do_assign = 1; @@ -185,6 +256,9 @@ DEFUN(__vfscanf, (s, format, arg), switch (*f++) { case '*': +#ifdef USE_IN_LIBIO + flags = SUPPRESS; +#endif do_assign = 0; break; case '\'': @@ -192,9 +266,15 @@ DEFUN(__vfscanf, (s, format, arg), break; } +#ifdef USE_IN_LIBIO + /* We have seen width. */ + if (isdigit (*f)) + flags |= WIDTH; +#endif + /* Find the maximum field width. */ width = 0; - while (isdigit(*f)) + while (isdigit (*f)) { width *= 10; width += *f++ - '0'; @@ -209,19 +289,44 @@ DEFUN(__vfscanf, (s, format, arg), { case 'h': /* int's are short int's. */ +#ifdef USE_IN_LIBIO + if (flags & ~(SUPPRESS | WIDTH)) + /* Signal illegal format element. */ + conv_error (); + flags |= SHORT; +#endif is_short = 1; break; case 'l': if (is_long) - /* A double `l' is equivalent to an `L'. */ - is_longlong = 1; + { + /* A double `l' is equivalent to an `L'. */ +#ifdef USE_IN_LIBIO + if ((flags & ~(SUPPRESS | WIDTH)) && (flags & LONGDBL)) + conv_error (); + flags &= ~LONG; + flags |= LONGDBL; +#endif + is_longlong = 1; + } else - /* int's are long int's. */ - is_long = 1; + { + /* int's are long int's. */ +#ifdef USE_IN_LIBIO + flags |= LONG; +#endif + is_long = 1; + } break; case 'q': case 'L': /* double's are long double's, and int's are long long int's. */ +#ifdef USE_IN_LIBIO + if (flags & ~(SUPPRESS | WIDTH)) + /* Signal illegal format element. */ + conv_error (); + flags |= LONGDBL; +#endif is_long_double = 1; break; case 'a': @@ -233,20 +338,20 @@ DEFUN(__vfscanf, (s, format, arg), /* End of the format string? */ if (*f == '\0') - conv_error(); + conv_error (); /* Find the conversion specifier. */ w = work; fc = *f++; if (fc != '[' && fc != 'c' && fc != 'n') /* Eat whitespace. */ - while (isspace(c)) - (void) inchar(); + while (isspace (c)) + (void) inchar (); switch (fc) { case '%': /* Must match a literal '%'. */ if (c != fc) - conv_error(); + conv_error (); break; case 'n': /* Answer number of assignments done. */ @@ -263,7 +368,7 @@ DEFUN(__vfscanf, (s, format, arg), } if (c == EOF) - input_error(); + input_error (); if (width == -1) width = 1; @@ -272,10 +377,10 @@ DEFUN(__vfscanf, (s, format, arg), { do *str++ = c; - while (inchar() != EOF && --width > 0); + while (inchar () != EOF && --width > 0); } else - while (inchar() != EOF && --width > 0); + while (inchar () != EOF && --width > 0); if (do_assign) ++done; @@ -289,7 +394,7 @@ DEFUN(__vfscanf, (s, format, arg), if (malloc_string) \ { \ /* The string is to be stored in a malloc'd buffer. */ \ - strptr = ARG (char **); \ + strptr = ARG (char **); \ if (strptr == NULL) \ conv_error (); \ /* Allocate an initial buffer. */ \ @@ -297,7 +402,7 @@ DEFUN(__vfscanf, (s, format, arg), *strptr = str = malloc (strsize); \ } \ else \ - str = ARG (char *); \ + str = ARG (char *); \ if (str == NULL) \ conv_error (); \ } @@ -357,7 +462,7 @@ DEFUN(__vfscanf, (s, format, arg), break; case 'x': /* Hexadecimal integer. */ - case 'X': /* Ditto. */ + case 'X': /* Ditto. */ base = 16; number_signed = 0; goto number; @@ -383,7 +488,7 @@ DEFUN(__vfscanf, (s, format, arg), number: if (c == EOF) - input_error(); + input_error (); /* Check for a sign. */ if (c == '-' || c == '+') @@ -391,7 +496,7 @@ DEFUN(__vfscanf, (s, format, arg), *w++ = c; if (width > 0) --width; - (void) inchar(); + (void) inchar (); } /* Look for a leading indication of base. */ @@ -401,9 +506,9 @@ DEFUN(__vfscanf, (s, format, arg), --width; *w++ = '0'; - (void) inchar(); + (void) inchar (); - if (tolower(c) == 'x') + if (tolower (c) == 'x') { if (base == 0) base = 16; @@ -411,7 +516,7 @@ DEFUN(__vfscanf, (s, format, arg), { if (width > 0) --width; - (void) inchar(); + (void) inchar (); } } else if (base == 0) @@ -422,21 +527,21 @@ DEFUN(__vfscanf, (s, format, arg), base = 10; /* Read the number into WORK. */ - while (width != 0 && c != EOF) + do { - if (base == 16 ? !isxdigit(c) : - (!isdigit(c) || c - '0' >= base)) + if (base == 16 ? !isxdigit (c) : + (!isdigit (c) || c - '0' >= base)) break; *w++ = c; if (width > 0) --width; - (void) inchar (); } + while (inchar () != EOF && width != 0); if (w == work || (w - work == 1 && (work[0] == '+' || work[0] == '-'))) /* There was no number. */ - conv_error(); + conv_error (); /* Convert the number. */ *w = '\0'; @@ -492,15 +597,15 @@ DEFUN(__vfscanf, (s, format, arg), case 'g': case 'G': if (c == EOF) - input_error(); + input_error (); /* Check for a sign. */ if (c == '-' || c == '+') { *w++ = c; - if (inchar() == EOF) + if (inchar () == EOF) /* EOF is only an input error before we read any chars. */ - conv_error(); + conv_error (); if (width > 0) --width; } @@ -508,11 +613,11 @@ DEFUN(__vfscanf, (s, format, arg), got_dot = got_e = 0; do { - if (isdigit(c)) + if (isdigit (c)) *w++ = c; else if (got_e && w[-1] == 'e' && (c == '-' || c == '+')) *w++ = c; - else if (!got_e && tolower(c) == 'e') + else if (!got_e && tolower (c) == 'e') { *w++ = 'e'; got_e = got_dot = 1; @@ -526,12 +631,12 @@ DEFUN(__vfscanf, (s, format, arg), break; if (width > 0) --width; - } while (inchar() != EOF && width != 0); + } while (inchar () != EOF && width != 0); if (w == work) conv_error(); if (w[-1] == '-' || w[-1] == '+' || w[-1] == 'e') - conv_error(); + conv_error (); /* Convert the number. */ *w = '\0'; @@ -614,11 +719,14 @@ DEFUN(__vfscanf, (s, format, arg), base = 16; /* A PTR must be the same size as a `long int'. */ is_long = 1; + number_signed = 0; goto number; } } - conv_error(); + return ((c == EOF || ungetc (c, s)), done); } +#ifndef USE_IN_LIBIO weak_alias (__vfscanf, vfscanf) +#endif diff --git a/stdlib/strtod.c b/stdlib/strtod.c index b7c717a823..e60617ffac 100644 --- a/stdlib/strtod.c +++ b/stdlib/strtod.c @@ -70,7 +70,7 @@ extern FLOAT MPN2FLOAT (mp_srcptr mpn, int exponent, int negative); # define MAX_DIG_PER_LIMB 19 # define MAX_FAC_PER_LIMB 10000000000000000000L #else -# error "mp_limb size " BITS_PER_MP_LIMB "not accounted for" +# error "mp_limb size " BITS_PER_MP_LIMB "not accounted for" #endif @@ -102,7 +102,7 @@ static const mp_limb _tens_in_limb[MAX_DIG_PER_LIMB + 1] = #define RETURN(val,end) \ do { if (endptr != 0) *endptr = (char *) (end); return val; } while (0) -/* Maximum size necessary for mpn integers to hold floating point numbers. */ +/* Maximum size necessary for mpn integers to hold floating point numbers. */ #define MPNSIZE (howmany (MAX_EXP + 2 * MANT_DIG, BITS_PER_MP_LIMB) \ + 2) /* Declare an mpn integer variable that big. */ @@ -584,7 +584,7 @@ INTERNAL (STRTOF) (nptr, endptr, group) { errno = ERANGE; return 0.0; - } + } if (int_no > 0) { @@ -797,7 +797,7 @@ INTERNAL (STRTOF) (nptr, endptr, group) dig_no -= lead_zero; } - /* Read the fractional digits from the string. */ + /* Read the fractional digits from the string. */ (void) str_to_mpn (startp, dig_no - int_no, num, &numsize, &exponent); @@ -964,7 +964,7 @@ INTERNAL (STRTOF) (nptr, endptr, group) have_quot: got_limb; } - + return round_and_return (retval, exponent - 1, negative, quot, BITS_PER_MP_LIMB - 1 - used, more_bits || n1 != 0 || n0 != 0); @@ -1105,9 +1105,6 @@ INTERNAL (STRTOF) (nptr, endptr, group) /* External user entry point. */ -#define weak_this(x) weak_symbol(x) -weak_this (STRTOF) - FLOAT STRTOF (nptr, endptr) const char *nptr; @@ -1115,3 +1112,6 @@ STRTOF (nptr, endptr) { return INTERNAL (STRTOF) (nptr, endptr, 0); } + +#define weak_this(x) weak_symbol(x) +weak_this (STRTOF) diff --git a/stdlib/strtol.c b/stdlib/strtol.c index 8c1a683880..d52f338c84 100644 --- a/stdlib/strtol.c +++ b/stdlib/strtol.c @@ -277,10 +277,6 @@ noconv: /* External user entry point. */ -#ifdef weak_symbol -weak_symbol (strtol) -#endif - INT strtol (nptr, endptr, base) const char *nptr; @@ -289,3 +285,7 @@ strtol (nptr, endptr, base) { return INTERNAL (strtol) (nptr, endptr, base, 0); } + +#ifdef weak_symbol +weak_symbol (strtol) +#endif diff --git a/sysdeps/posix/tempname.c b/sysdeps/posix/tempname.c index f2da66a211..c70a6e8d35 100644 --- a/sysdeps/posix/tempname.c +++ b/sysdeps/posix/tempname.c @@ -27,6 +27,11 @@ Cambridge, MA 02139, USA. */ #include <fcntl.h> #include <unistd.h> +#ifdef USE_IN_LIBIO +# include "libioP.h" +# include <libio.h> +#endif + /* Return nonzero if DIR is an existent directory. */ static int DEFUN(diraccess, (dir), CONST char *dir) @@ -169,6 +174,41 @@ DEFUN(__stdio_gen_tempname, (dir, pfx, dir_search, lenptr, streamptr), { /* We got a new file that did not previously exist. Create a stream for it. */ +#ifdef USE_IN_LIBIO + int save; + struct _IO_FILE_plus *fp; + + fp = (struct _IO_FILE_plus *) + malloc(sizeof (struct _IO_FILE_plus)); + if (fp == NULL) + { + /* We lost trying to create a stream (out of memory?). + Nothing to do but remove the file, close the descriptor, + and return failure. */ + save = errno; + lose: + (void) remove (buf); + (void) __close (fd); + errno = save; + return NULL; + } + _IO_init (&fp->file, 0); + _IO_JUMPS (&fp->file) = &_IO_file_jumps; + _IO_file_init (&fp->file); +# if !_IO_UNIFIED_JUMPTABLES + fp->vtable = NULL; +# endif + if (_IO_file_attach (&fp->file, fd) == NULL) + { + save = errno; + free (fp); + goto lose; + } + fp->file._flags &= ~_IO_DELETE_DONT_CLOSE; + fp->file._IO_file_flags = 0; + + *streamptr = (FILE *) fp; +#else *streamptr = __newstream (); if (*streamptr == NULL) { @@ -185,6 +225,7 @@ DEFUN(__stdio_gen_tempname, (dir, pfx, dir_search, lenptr, streamptr), (*streamptr)->__mode.__write = 1; (*streamptr)->__mode.__read = 1; (*streamptr)->__mode.__binary = 1; +#endif } else continue; diff --git a/sysdeps/unix/sysv/linux/configure b/sysdeps/unix/sysv/linux/configure new file mode 100644 index 0000000000..63693e088e --- /dev/null +++ b/sysdeps/unix/sysv/linux/configure @@ -0,0 +1,3 @@ +# On Linux, the default is to use libio instead of stdio. + +test $stdio = default && stdio=libio |