diff options
| author | phil <phil@NetBSD.org> | 1996-03-09 00:00:51 +0000 |
|---|---|---|
| committer | phil <phil@NetBSD.org> | 1996-03-09 00:00:51 +0000 |
| commit | 357744cd54478d5d74cb52cd1459eb7c26192abd (patch) | |
| tree | 32a89fdf6e6be53376907dd269e63ad8a9584a79 /gnu/lib/libg++/libio | |
| parent | 2c11ad408cd834f9e23a25702550639628396204 (diff) | |
Import of libg++-2.7.1.
Diffstat (limited to 'gnu/lib/libg++/libio')
98 files changed, 15729 insertions, 0 deletions
diff --git a/gnu/lib/libg++/libio/Makefile b/gnu/lib/libg++/libio/Makefile new file mode 100644 index 00000000000..158971bbbfc --- /dev/null +++ b/gnu/lib/libg++/libio/Makefile @@ -0,0 +1,18 @@ +# $NetBSD: Makefile,v 1.1.1.1 1996/03/09 00:01:31 phil Exp $ + +LIB= io + +SRCS= cleanup.c filedoalloc.c fileops.c floatconv.c genops.c iofclose.c \ +iofdopen.c iofflush.c iofgetpos.c iofgets.c iofopen.c iofprintf.c \ +iofputs.c iofread.c iofscanf.c iofsetpos.c ioftell.c iofwrite.c \ +iogetdelim.c iogetline.c iogets.c ioignore.c iopadn.c ioperror.c \ +iopopen.c ioprims.c ioprintf.c ioputs.c ioscanf.c ioseekoff.c \ +ioseekpos.c iosetbuffer.c iosetvbuf.c iosprintf.c iosscanf.c iostrerror.c \ +ioungetc.c iovfprintf.c iovfscanf.c iovsprintf.c iovsscanf.c outfloat.c \ +stdfiles.c strops.c + +CXXFLAGS+= -nostdinc++ -I$(.CURDIR)/../include +CFLAGS+= -I$(.CURDIR) +NOMAN= noman + +.include <bsd.lib.mk> diff --git a/gnu/lib/libg++/libio/PlotFile.cc b/gnu/lib/libg++/libio/PlotFile.cc new file mode 100644 index 00000000000..98b2d839555 --- /dev/null +++ b/gnu/lib/libg++/libio/PlotFile.cc @@ -0,0 +1,157 @@ +/* +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. */ + +// This may look like C code, but it is really -*- C++ -*- +/* +Copyright (C) 1988, 1992, 1993 Free Software Foundation + written by Doug Lea (dl@rocky.oswego.edu) + converted to use iostream library by Per Bothner (bothner@cygnus.com) + +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 GCC 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 __GNUG__ +#pragma implementation +#endif +#include <PlotFile.h> + +/* + PlotFile implementation module +*/ + + +PlotFile& PlotFile:: cmd(char c) +{ + ofstream::put(c); + return *this; +} + +PlotFile& PlotFile:: operator<<(const int x) +{ +#if defined(convex) + ofstream::put((char)(x>>8)); + ofstream::put((char)(x&0377)); +#else + ofstream::put((char)(x&0377)); + ofstream::put((char)(x>>8)); +#endif + return *this; +} + +PlotFile& PlotFile:: operator<<(const char *s) +{ + *(ofstream*)this << s; + return *this; +} + + +PlotFile& PlotFile:: arc(const int xi, const int yi, + const int x0, const int y0, + const int x1, const int y1) +{ + return cmd('a') << xi << yi << x0 << y0 << x1 << y1; +} + + +PlotFile& PlotFile:: box(const int x0, const int y0, + const int x1, const int y1) +{ + line(x0, y0, x0, y1); + line(x0, y1, x1, y1); + line(x1, y1, x1, y0); + return line(x1, y0, x0, y0); +} + +PlotFile& PlotFile:: circle(const int x, const int y, const int r) +{ + return cmd('c') << x << y << r; +} + +PlotFile& PlotFile:: cont(const int xi, const int yi) +{ + return cmd('n') << xi << yi; +} + +PlotFile& PlotFile:: dot(const int xi, const int yi, const int dx, + int n, const int* pat) +{ + cmd('d') << xi << yi << dx << n; + while (n-- > 0) *this << *pat++; + return *this; +} + +PlotFile& PlotFile:: erase() +{ + return cmd('e'); +} + +PlotFile& PlotFile:: label(const char* s) +{ + return cmd('t') << s << "\n"; +} + +PlotFile& PlotFile:: line(const int x0, const int y0, + const int x1, const int y1) +{ + return cmd('l') << x0 << y0 << x1 << y1; +} + +PlotFile& PlotFile:: linemod(const char* s) +{ + return cmd('f') << s << "\n"; +} + +PlotFile& PlotFile:: move(const int xi, const int yi) +{ + return cmd('m') << xi << yi; +} + +PlotFile& PlotFile:: point(const int xi, const int yi) +{ + return cmd('p') << xi << yi; +} + +PlotFile& PlotFile:: space(const int x0, const int y0, + const int x1, const int y1) +{ + return cmd('s') << x0 << y0 << x1 << y1; +} diff --git a/gnu/lib/libg++/libio/PlotFile.h b/gnu/lib/libg++/libio/PlotFile.h new file mode 100644 index 00000000000..82b08bc4681 --- /dev/null +++ b/gnu/lib/libg++/libio/PlotFile.h @@ -0,0 +1,89 @@ +/* This is part of libio/iostream, providing -*- C++ -*- input/output. +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. */ + +/* + a very simple implementation of a class to output unix "plot" + format plotter files. See corresponding unix man pages for + more details. + + written by Doug Lea (dl@rocky.oswego.edu) + converted to use iostream library by Per Bothner (bothner@cygnus.com) +*/ + +#ifndef _PlotFile_h +#ifdef __GNUG__ +#pragma interface +#endif +#define _PlotFile_h + +#include <fstream.h> + +/* + Some plot libraries have the `box' command to draw boxes. Some don't. + `box' is included here via moves & lines to allow both possiblilties. +*/ + +extern "C++" { +class PlotFile : public ofstream +{ +protected: + PlotFile& cmd(char c); + PlotFile& operator << (const int x); + PlotFile& operator << (const char *s); + +public: + + PlotFile() : ofstream() { } + PlotFile(int fd) : ofstream(fd) { } + PlotFile(const char *name, int mode=ios::out, int prot=0664) + : ofstream(name, mode, prot) { } + +// PlotFile& remove() { ofstream::remove(); return *this; } + +// int filedesc() { return ofstream::filedesc(); } +// const char* name() { return File::name(); } +// void setname(const char* newname) { File::setname(newname); } +// int iocount() { return File::iocount(); } + + PlotFile& arc(const int xi, const int yi, + const int x0, const int y0, + const int x1, const int y1); + PlotFile& box(const int x0, const int y0, + const int x1, const int y1); + PlotFile& circle(const int x, const int y, const int r); + PlotFile& cont(const int xi, const int yi); + PlotFile& dot(const int xi, const int yi, const int dx, + int n, const int* pat); + PlotFile& erase(); + PlotFile& label(const char* s); + PlotFile& line(const int x0, const int y0, + const int x1, const int y1); + PlotFile& linemod(const char* s); + PlotFile& move(const int xi, const int yi); + PlotFile& point(const int xi, const int yi); + PlotFile& space(const int x0, const int y0, + const int x1, const int y1); +}; +} // extern "C++" +#endif diff --git a/gnu/lib/libg++/libio/SFile.cc b/gnu/lib/libg++/libio/SFile.cc new file mode 100644 index 00000000000..e5daa645695 --- /dev/null +++ b/gnu/lib/libg++/libio/SFile.cc @@ -0,0 +1,82 @@ +/* +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) 1988 Free Software Foundation + written by Doug Lea (dl@rocky.oswego.edu) + +This file is part of the GNU C++ Library. 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, 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. +*/ + +#ifdef __GNUG__ +#pragma implementation +#endif +#include <SFile.h> + +SFile::SFile(const char *filename, int size, int mode, int prot) +: fstream(filename, mode, prot) +{ + sz = size; +} + +SFile::SFile(int fd, int size) +: fstream(fd) +{ + sz = size; +} + +void SFile::open(const char *name, int size, int mode, int prot) +{ + fstream::open(name, mode, prot); + sz = size; +} + +SFile& SFile::get(void* x) +{ + read(x, sz); + return *this; +} + +SFile& SFile::put(void* x) +{ + write(x, sz); + return *this; +} + +SFile& SFile::operator[](long i) +{ + if (rdbuf()->pubseekoff(i * sz, ios::beg) == EOF) + set(ios::badbit); + return *this; +} diff --git a/gnu/lib/libg++/libio/SFile.h b/gnu/lib/libg++/libio/SFile.h new file mode 100644 index 00000000000..f07277cee49 --- /dev/null +++ b/gnu/lib/libg++/libio/SFile.h @@ -0,0 +1,55 @@ +/* This is part of libio/iostream, providing -*- C++ -*- input/output. +Copyright (C) 1988, 1992, 1993 Free Software Foundation + written by Doug Lea (dl@rocky.oswego.edu) + +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. */ + +#ifndef _SFile_h +#ifdef __GNUG__ +#pragma interface +#endif +#define _SFile_h 1 + +#include <fstream.h> + +extern "C++" { +class SFile: public fstream +{ + protected: + int sz; // unit size for structured binary IO + +public: + SFile() : fstream() { } + SFile(int fd, int size); + SFile(const char *name, int size, int mode, int prot=0664); + void open(const char *name, int size, int mode, int prot=0664); + + int size() { return sz; } + int setsize(int s) { int old = sz; sz = s; return old; } + + SFile& get(void* x); + SFile& put(void* x); + SFile& operator[](long i); +}; +} // extern "C++" + +#endif diff --git a/gnu/lib/libg++/libio/_G_config.h b/gnu/lib/libg++/libio/_G_config.h new file mode 100644 index 00000000000..a8b1066e716 --- /dev/null +++ b/gnu/lib/libg++/libio/_G_config.h @@ -0,0 +1,78 @@ +/* AUTOMATICALLY GENERATED; DO NOT EDIT! */ +#ifndef _G_config_h +#define _G_config_h +#define _G_LIB_VERSION "2.7.1" +#define _G_NAMES_HAVE_UNDERSCORE 1 +#define _G_VTABLE_LABEL_HAS_LENGTH 1 +#define _G_VTABLE_LABEL_PREFIX "__vt$" +#define _G_HAVE_ST_BLKSIZE 1 +typedef unsigned long _G_clock_t; +typedef int _G_dev_t; +typedef long long _G_fpos_t; +typedef unsigned int _G_gid_t; +typedef unsigned int _G_ino_t; +typedef unsigned short _G_mode_t; +typedef unsigned short _G_nlink_t; +typedef long long _G_off_t; +typedef int _G_pid_t; +#ifndef __PTRDIFF_TYPE__ +#define __PTRDIFF_TYPE__ int +#endif +typedef __PTRDIFF_TYPE__ _G_ptrdiff_t; +typedef unsigned int _G_sigset_t; +#ifndef __SIZE_TYPE__ +#define __SIZE_TYPE__ unsigned int +#endif +typedef __SIZE_TYPE__ _G_size_t; +typedef long _G_time_t; +typedef unsigned int _G_uid_t; +typedef int _G_wchar_t; +typedef int _G_ssize_t; +typedef int /* default */ _G_wint_t; +typedef char * _G_va_list; +#define _G_signal_return_type void +#define _G_sprintf_return_type int + +#if __GNUC__ > 2 || (__GNUC__ == 2 && __GNUC_MINOR__ >= 7) +typedef int _G_int8_t __attribute__((__mode__(__QI__))); +typedef unsigned int _G_uint8_t __attribute__((__mode__(__QI__))); +typedef int _G_int16_t __attribute__((__mode__(__HI__))); +typedef unsigned int _G_uint16_t __attribute__((__mode__(__HI__))); +typedef int _G_int32_t __attribute__((__mode__(__SI__))); +typedef unsigned int _G_uint32_t __attribute__((__mode__(__SI__))); +typedef int _G_int64_t __attribute__((__mode__(__DI__))); +typedef unsigned int _G_uint64_t __attribute__((__mode__(__DI__))); +#else +typedef short _G_int16_t; +typedef unsigned short _G_uint16_t; +typedef int _G_int32_t; +typedef unsigned int _G_uint32_t; +#endif + +#define _G_BUFSIZ 1024 +#define _G_FOPEN_MAX 20 +#define _G_FILENAME_MAX 1024 +#define _G_NULL 0 /* default */ +#if defined (__cplusplus) || defined (__STDC__) +#define _G_ARGS(ARGLIST) ARGLIST +#else +#define _G_ARGS(ARGLIST) () +#endif +#if !defined (__GNUG__) || defined (__STRICT_ANSI__) +#define _G_NO_NRV +#endif +#if !defined (__GNUG__) +#define _G_NO_EXTERN_TEMPLATES +#endif +#define _G_HAVE_ATEXIT 1 +#define _G_HAVE_SYS_RESOURCE 1 +#define _G_HAVE_SYS_TIMES 1 +#define _G_HAVE_SYS_SOCKET 1 +#define _G_HAVE_SYS_CDEFS 1 +#define _G_HAVE_SYS_WAIT 1 +#define _G_HAVE_UNISTD 1 +#define _G_HAVE_DIRENT 1 +#define _G_HAVE_CURSES 1 +#define _G_MATH_H_INLINES 0 +#define _G_HAVE_BOOL 1 +#endif /* !_G_config_h */ diff --git a/gnu/lib/libg++/libio/builtinbuf.cc b/gnu/lib/libg++/libio/builtinbuf.cc new file mode 100644 index 00000000000..05e65a5c371 --- /dev/null +++ b/gnu/lib/libg++/libio/builtinbuf.cc @@ -0,0 +1,78 @@ +/* +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. */ + +#ifdef __GNUC__ +#pragma implementation +#endif +#define _STREAM_COMPAT +#include "builtinbuf.h" +#include "iostreamP.h" +#if !_IO_UNIFIED_JUMPTABLES +int builtinbuf::overflow(int ch) { return _IO_OVERFLOW (this, ch); } + +int builtinbuf::underflow() { return _IO_UNDERFLOW (this); } + +streamsize builtinbuf::xsgetn(char* buf, streamsize n) +{ return _IO_XSGETN (this, buf, n); } + +streamsize builtinbuf::xsputn(const char* buf, streamsize n) +{ return _IO_XSPUTN (this, buf, n); } + +int builtinbuf::doallocate() { return _IO_DOALLOCATE (this); } + +builtinbuf::~builtinbuf() { _IO_FINISH (this); } + +int builtinbuf::sync() { return _IO_SYNC (this); } + +streambuf* builtinbuf::setbuf(char *buf, int n) +{ return (streambuf*)_IO_SETBUF (this, buf, n); } + +streampos builtinbuf::seekoff(streamoff off, _seek_dir dir, int mode) +{ + return _IO_SEEKOFF (this, off, dir, mode); +} + +streampos builtinbuf::seekpos(streampos pos, int mode) +{ + return _IO_SEEKPOS (this, pos, mode); +} + +int builtinbuf::pbackfail(int c) +{ return _IO_PBACKFAIL (this, c); } + +streamsize builtinbuf::sys_read(char* buf, streamsize size) +{ return _IO_SYSREAD (this, buf, size); } + +streampos builtinbuf::sys_seek(streamoff off, _seek_dir dir) +{ return _IO_SYSSEEK (this, off, dir); } + +streamsize builtinbuf::sys_write(const char* buf, streamsize size) +{ return _IO_SYSWRITE (this, buf, size); } + +int builtinbuf::sys_stat(void* buf) // Actually, a (struct stat*) +{ return _IO_SYSSTAT (this, buf); } + +int builtinbuf::sys_close() +{ return _IO_SYSCLOSE (this); } +#endif diff --git a/gnu/lib/libg++/libio/builtinbuf.h b/gnu/lib/libg++/libio/builtinbuf.h new file mode 100644 index 00000000000..0e0c6e85a9e --- /dev/null +++ b/gnu/lib/libg++/libio/builtinbuf.h @@ -0,0 +1,68 @@ +/* +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. */ + +#ifndef _BUILTINBUF_H +#define _BUILTINBUF_H + +#ifdef __GNUC__ +#pragma interface +#endif + +#include <streambuf.h> + +#if !_IO_UNIFIED_JUMPTABLES +// A builtinbuf a a streambuf where all the virtual operations +// call the _IO_jump_t table. + +extern "C++" { +class builtinbuf : public streambuf { + friend ios; + virtual int overflow(int); + virtual int underflow(); + virtual streamsize xsgetn(char *, streamsize); + virtual streamsize xsputn(const char *, streamsize); + virtual streambuf* setbuf(char*, int); + virtual int doallocate(); + virtual ~builtinbuf(); + virtual int sync(); + + virtual streampos seekoff(streamoff, _seek_dir, int mode=ios::in|ios::out); + virtual streampos seekpos(streampos pos, int mode = ios::in|ios::out); + virtual int pbackfail(int c); + virtual streamsize sys_read(char* buf, streamsize size); + virtual streampos sys_seek(streamoff, _seek_dir); + virtual streamsize sys_write(const char*, streamsize); + virtual int sys_stat(void*); // Actually, a (struct stat*) + virtual int sys_close(); +#if 0 + virtual int get_column(); + virtual int set_column(int); +#endif + private: + builtinbuf() { } +}; +} // extern "C++" +#endif + +#endif /* _BUILTINBUF_H */ diff --git a/gnu/lib/libg++/libio/cleanup.c b/gnu/lib/libg++/libio/cleanup.c new file mode 100644 index 00000000000..b4c8be927f9 --- /dev/null +++ b/gnu/lib/libg++/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/gnu/lib/libg++/libio/editbuf.cc b/gnu/lib/libg++/libio/editbuf.cc new file mode 100644 index 00000000000..22304820f8f --- /dev/null +++ b/gnu/lib/libg++/libio/editbuf.cc @@ -0,0 +1,717 @@ +/* This is part of libio/iostream, providing -*- C++ -*- input/output. +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. + +Written by Per Bothner (bothner@cygnus.com). */ + +#ifdef __GNUG__ +#pragma implementation +#endif +#include "libioP.h" +#include "editbuf.h" +#include <stddef.h> +#include <stdlib.h> + +/* NOTE: Some of the code here is taken from GNU emacs */ +/* Hence this file falls under the GNU License! */ + +// Invariants for edit_streambuf: +// An edit_streambuf is associated with a specific edit_string, +// which again is a sub-string of a specific edit_buffer. +// An edit_streambuf is always in either get mode or put mode, never both. +// In get mode, gptr() is the current position, +// and pbase(), pptr(), and epptr() are all NULL. +// In put mode, pptr() is the current position, +// and eback(), gptr(), and egptr() are all NULL. +// Any edit_streambuf that is actively doing insertion (as opposed to +// replacing) // must have its pptr() pointing to the start of the gap. +// Only one edit_streambuf can be actively inserting into a specific +// edit_buffer; the edit_buffer's _writer field points to that edit_streambuf. +// That edit_streambuf "owns" the gap, and the actual start of the +// gap is the pptr() of the edit_streambuf; the edit_buffer::_gap_start pointer +// will only be updated on an edit_streambuf::overflow(). + +int edit_streambuf::truncate() +{ + str->buffer->delete_range(str->buffer->tell((buf_char*)pptr()), + str->buffer->tell(str->end)); + return 0; +} + +#ifdef OLD_STDIO +inline void disconnect_gap_from_file(edit_buffer* buffer, FILE* fp) +{ + if (buffer->gap_start_ptr != &fp->__bufp) + return; + buffer->gap_start_normal = fp->__bufp; + buffer->gap_start_ptr = &buffer->gap_start_normal; +} +#endif + +void edit_streambuf::flush_to_buffer(edit_buffer* buffer) +{ + if (pptr() > buffer->_gap_start && pptr() < buffer->gap_end()) + buffer->_gap_start = pptr(); +} + +void edit_streambuf::disconnect_gap_from_file(edit_buffer* buffer) +{ + if (buffer->_writer != this) return; + flush_to_buffer(buffer); + setp(pptr(),pptr()); + buffer->_writer = NULL; +} + +buf_index edit_buffer::tell(buf_char *ptr) +{ + if (ptr <= gap_start()) + return ptr - data; + else + return ptr - gap_end() + size1(); +} + +#if 0 +buf_index buf_cookie::tell() +{ + return str->buffer->tell(file->__bufp); +} +#endif + +buf_index edit_buffer::tell(edit_mark*mark) +{ + return tell(data + mark->index_in_buffer(this)); +} + +// adjust the position of the gap + +void edit_buffer::move_gap(buf_offset pos) +{ + if (pos < size1()) + gap_left (pos); + else if (pos > size1()) + gap_right (pos); +} + +void edit_buffer::gap_left (int pos) +{ + register buf_char *to, *from; + register int i; + int new_s1; + + i = size1(); + from = gap_start(); + to = from + gap_size(); + new_s1 = size1(); + + /* Now copy the characters. To move the gap down, + copy characters up. */ + + for (;;) + { + /* I gets number of characters left to copy. */ + i = new_s1 - pos; + if (i == 0) + break; +#if 0 + /* If a quit is requested, stop copying now. + Change POS to be where we have actually moved the gap to. */ + if (QUITP) + { + pos = new_s1; + break; + } +#endif + /* Move at most 32000 chars before checking again for a quit. */ + if (i > 32000) + i = 32000; + new_s1 -= i; + while (--i >= 0) + *--to = *--from; + } + + /* Adjust markers, and buffer data structure, to put the gap at POS. + POS is where the loop above stopped, which may be what was specified + or may be where a quit was detected. */ + adjust_markers (pos << 1, size1() << 1, gap_size(), data); +#ifndef OLD_STDIO + _gap_start = data + pos; +#else + if (gap_start_ptr == &gap_start_normal) + gap_start_normal = data + pos; +#endif + __gap_end_pos = to - data; +/* QUIT;*/ +} + +void edit_buffer::gap_right (int pos) +{ + register buf_char *to, *from; + register int i; + int new_s1; + + i = size1(); + to = gap_start(); + from = i + gap_end(); + new_s1 = i; + + /* Now copy the characters. To move the gap up, + copy characters down. */ + + while (1) + { + /* I gets number of characters left to copy. */ + i = pos - new_s1; + if (i == 0) + break; +#if 0 + /* If a quit is requested, stop copying now. + Change POS to be where we have actually moved the gap to. */ + if (QUITP) + { + pos = new_s1; + break; + } +#endif + /* Move at most 32000 chars before checking again for a quit. */ + if (i > 32000) + i = 32000; + new_s1 += i; + while (--i >= 0) + *to++ = *from++; + } + + adjust_markers ((size1() + gap_size()) << 1, (pos + gap_size()) << 1, + - gap_size(), data); +#ifndef OLD_STDIO + _gap_start = data+pos; +#else + if (gap_start_ptr == &gap_start_normal) + gap_start_normal = data + pos; +#endif + __gap_end_pos = from - data; +/* QUIT;*/ +} + +/* make sure that the gap in the current buffer is at least k + characters wide */ + +void edit_buffer::make_gap(buf_offset k) +{ + register buf_char *p1, *p2, *lim; + buf_char *old_data = data; + int s1 = size1(); + + if (gap_size() >= k) + return; + + /* Get more than just enough */ + if (buf_size > 1000) k += 2000; + else k += /*200;*/ 20; // for testing! + + p1 = (buf_char *) realloc (data, s1 + size2() + k); + if (p1 == 0) + abort(); /*memory_full ();*/ + + k -= gap_size(); /* Amount of increase. */ + + /* Record new location of text */ + data = p1; + + /* Transfer the new free space from the end to the gap + by shifting the second segment upward */ + p2 = data + buf_size; + p1 = p2 + k; + lim = p2 - size2(); + while (lim < p2) + *--p1 = *--p2; + + /* Finish updating text location data */ + __gap_end_pos += k; + +#ifndef OLD_STDIO + _gap_start = data + s1; +#else + if (gap_start_ptr == &gap_start_normal) + gap_start_normal = data + s1; +#endif + + /* adjust markers */ + adjust_markers (s1 << 1, (buf_size << 1) + 1, k, old_data); + buf_size += k; +} + +/* Add `amount' to the position of every marker in the current buffer + whose current position is between `from' (exclusive) and `to' (inclusive). + Also, any markers past the outside of that interval, in the direction + of adjustment, are first moved back to the near end of the interval + and then adjusted by `amount'. */ + +void edit_buffer::adjust_markers(register mark_pointer low, + register mark_pointer high, + int amount, buf_char *old_data) +{ + register struct edit_mark *m; + register mark_pointer mpos; + /* convert to mark_pointer */ + amount <<= 1; + + if (_writer) + _writer->disconnect_gap_from_file(this); + + for (m = mark_list(); m != NULL; m = m->chain) + { + mpos = m->_pos; + if (amount > 0) + { + if (mpos > high && mpos < high + amount) + mpos = high + amount; + } + else + { + if (mpos > low + amount && mpos <= low) + mpos = low + amount; + } + if (mpos > low && mpos <= high) + mpos += amount; + m->_pos = mpos; + } + + // Now adjust files + edit_streambuf *file; + + for (file = files; file != NULL; file = file->next) { + mpos = file->current() - old_data; + if (amount > 0) + { + if (mpos > high && mpos < high + amount) + mpos = high + amount; + } + else + { + if (mpos > low + amount && mpos <= low) + mpos = low + amount; + } + if (mpos > low && mpos <= high) + mpos += amount; + char* new_pos = data + mpos; + file->set_current(new_pos, file->is_reading()); + } +} + +#if 0 +stdio_ + __off == index at start of buffer (need only be valid after seek ? ) + __buf == + +if read/read_delete/overwrite mode: + __endp <= min(*gap_start_ptr, edit_string->end->ptr(buffer)) + +if inserting: + must have *gap_start_ptr == __bufp && *gap_start_ptr+gap == __endp + file->edit_string->end->ptr(buffer) == *gap_start_ptr+end +if write_mode: + if before gap +#endif + +int edit_streambuf::underflow() +{ + if (!(_mode & ios::in)) + return EOF; + struct edit_buffer *buffer = str->buffer; + if (!is_reading()) { // Must switch from put to get mode. + disconnect_gap_from_file(buffer); + set_current(pptr(), 1); + } + buf_char *str_end = str->end->ptr(buffer); + retry: + if (gptr() < egptr()) { + return *gptr(); + } + if ((buf_char*)gptr() == str_end) + return EOF; + if (str_end <= buffer->gap_start()) { + setg(eback(), gptr(), str_end); + goto retry; + } + if (gptr() < buffer->gap_start()) { + setg(eback(), gptr(), buffer->gap_start()); + goto retry; + } + if (gptr() == buffer->gap_start()) { + disconnect_gap_from_file(buffer); +// fp->__offset += fp->__bufp - fp->__buffer; + setg(buffer->gap_end(), buffer->gap_end(), str_end); + } + else + setg(eback(), gptr(), str_end); + goto retry; +} + +int edit_streambuf::overflow(int ch) +{ + if (_mode == ios::in) + return EOF; + struct edit_buffer *buffer = str->buffer; + flush_to_buffer(buffer); + if (ch == EOF) + return 0; + if (is_reading()) { // Must switch from get to put mode. + set_current(gptr(), 0); + } + buf_char *str_end = str->end->ptr(buffer); + retry: + if (pptr() < epptr()) { + *pptr() = ch; + pbump(1); + return (unsigned char)ch; + } + if ((buf_char*)pptr() == str_end || inserting()) { + /* insert instead */ + if (buffer->_writer) + buffer->_writer->flush_to_buffer(); // Redundant? + buffer->_writer = NULL; + if (pptr() >= buffer->gap_end()) + buffer->move_gap(pptr() - buffer->gap_size()); + else + buffer->move_gap(pptr()); + buffer->make_gap(1); + setp(buffer->gap_start(), buffer->gap_end()); + buffer->_writer = this; + *pptr() = ch; + pbump(1); + return (unsigned char)ch; + } + if (str_end <= buffer->gap_start()) { + // Entire string is left of gap. + setp(pptr(), str_end); + } + else if (pptr() < buffer->gap_start()) { + // Current pos is left of gap. + setp(pptr(), buffer->gap_start()); + goto retry; + } + else if (pptr() == buffer->gap_start()) { + // Current pos is at start of gap; move to end of gap. +// disconnect_gap_from_file(buffer); + setp(buffer->gap_end(), str_end); +// __offset += __bufp - __buffer; + } + else { + // Otherwise, current pos is right of gap. + setp(pptr(), str_end); + } + goto retry; +} + +void edit_streambuf::set_current(char *new_pos, int reading) +{ + if (reading) { + setg(new_pos, new_pos, new_pos); + setp(NULL, NULL); + } + else { + setg(NULL, NULL, NULL); + setp(new_pos, new_pos); + } +} + +// Called by fseek(fp, pos, whence) if fp is bound to a edit_buffer. + +streampos edit_streambuf::seekoff(streamoff offset, _seek_dir dir, + int /* =ios::in|ios::out*/) +{ + struct edit_buffer *buffer = str->buffer; + disconnect_gap_from_file(buffer); + buf_index cur_pos = buffer->tell((buf_char*)current());; + buf_index start_pos = buffer->tell(str->start); + buf_index end_pos = buffer->tell(str->end); + switch (dir) { + case ios::beg: + offset += start_pos; + break; + case ios::cur: + offset += cur_pos; + break; + case ios::end: + offset += end_pos; + break; + } + if (offset < start_pos || offset > end_pos) + return EOF; + buf_char *new_pos = buffer->data + offset; + buf_char* gap_start = buffer->gap_start(); + if (new_pos > gap_start) { + buf_char* gap_end = buffer->gap_end(); + new_pos += gap_end - gap_start; + if (new_pos >= buffer->data + buffer->buf_size) abort(); // Paranoia. + } + set_current(new_pos, is_reading()); + return EOF; +} + +#if 0 +int buf_seek(void *arg_cookie, fpos_t * pos, int whence) +{ + struct buf_cookie *cookie = arg_cookie; + FILE *file = cookie->file; + struct edit_buffer *buffer = cookie->str->buffer; + buf_char *str_start = cookie->str->start->ptr(buffer); + disconnect_gap_from_file(buffer, cookie->file); + fpos_t cur_pos, new_pos; + if (file->__bufp <= *buffer->gap_start_ptr + || str_start >= buffer->__gap_end) + cur_pos = str_start - file->__bufp; + else + cur_pos = + (*buffer->gap_start_ptr - str_start) + (file->__bufp - __gap_end); + end_pos = ...; + switch (whence) { + case SEEK_SET: + new_pos = *pos; + break; + case SEEK_CUR: + new_pos = cur_pos + *pos; + break; + case SEEK_END: + new_pos = end_pos + *pos; + break; + } + if (new_pos > end_pos) { + seek to end_pos; + insert_nulls(new_pos - end_pos); + return; + } + if (str_start + new_pos <= *gap_start_ptr &* *gap_start_ptr < end) { + __buffer = str_start; + __off = 0; + __bufp = str_start + new_pos; + file->__get_limit = + *buffer->gap_start_ptr; /* what if gap_start_ptr == &bufp ??? */ + } else if () { + + } + *pos = new_pos; +} +#endif + +/* Delete characters from `from' up to (but not incl) `to' */ + +void edit_buffer::delete_range (buf_index from, buf_index to) +{ + register int numdel; + + if ((numdel = to - from) <= 0) + return; + + /* Make sure the gap is somewhere in or next to what we are deleting */ + if (from > size1()) + gap_right (from); + if (to < size1()) + gap_left (to); + + /* Relocate all markers pointing into the new, larger gap + to point at the end of the text before the gap. */ + adjust_markers ((to + gap_size()) << 1, (to + gap_size()) << 1, + - numdel - gap_size(), data); + + __gap_end_pos = to + gap_size(); + _gap_start = data + from; +} + +void edit_buffer::delete_range(struct edit_mark *start, struct edit_mark *end) +{ + delete_range(tell(start), tell(end)); +} + +void buf_delete_chars(struct edit_buffer *, struct edit_mark *, size_t) +{ + abort(); +} + +edit_streambuf::edit_streambuf(edit_string* bstr, int mode) +{ + _mode = mode; + str = bstr; + edit_buffer* buffer = bstr->buffer; + next = buffer->files; + buffer->files = this; + char* buf_ptr = bstr->start->ptr(buffer); + _inserting = 0; +// setb(buf_ptr, buf_ptr, 0); + set_current(buf_ptr, !(mode & ios::out+ios::trunc+ios::app)); + if (_mode & ios::trunc) + truncate(); + if (_mode & ios::ate) + seekoff(0, ios::end); +} + +// Called by fclose(fp) if fp is bound to a edit_buffer. + +#if 0 +static int buf_close(void *arg) +{ + register struct buf_cookie *cookie = arg; + struct edit_buffer *buffer = cookie->str->buffer; + struct buf_cookie **ptr; + for (ptr = &buffer->files; *ptr != cookie; ptr = &(*ptr)->next) ; + *ptr = cookie->next; + disconnect_gap_from_file(buffer, cookie->file); + free (cookie); + return 0; +} +#endif + +edit_streambuf::~edit_streambuf() +{ + if (_mode == ios::out) + truncate(); + // Unlink this from list of files associated with bstr->buffer. + edit_streambuf **ptr = &str->buffer->files; + for (; *ptr != this; ptr = &(*ptr)->next) { } + *ptr = next; + + disconnect_gap_from_file(str->buffer); +} + +edit_buffer::edit_buffer() +{ + buf_size = /*200;*/ 15; /* for testing! */ + data = (buf_char*)malloc(buf_size); + files = NULL; +#ifndef OLD_STDIO + _gap_start = data; + _writer = NULL; +#else + gap_start_normal = data; + gap_start_ptr = &gap_start_normal; +#endif + __gap_end_pos = buf_size; + start_mark.chain = &end_mark; + start_mark._pos = 0; + end_mark.chain = NULL; + end_mark._pos = 2 * buf_size + 1; +} + +// Allocate a new mark, which is adjusted by 'delta' bytes from 'this'. +// Restrict new mark to lie within 'str'. + +edit_mark::edit_mark(struct edit_string *str, long delta) +{ + struct edit_buffer *buf = str->buffer; + chain = buf->start_mark.chain; + buf->start_mark.chain = this; + mark_pointer size1 = buf->size1() << 1; + int gap_size = buf->gap_size() << 1; + delta <<= 1; + + // check if new and old marks are opposite sides of gap + if (_pos <= size1 && _pos + delta > size1) + delta += gap_size; + else if (_pos >= size1 + gap_size && _pos + delta < size1 + gap_size) + delta -= gap_size; + + _pos = _pos + delta; + if (_pos < str->start->_pos & ~1) + _pos = (str->start->_pos & ~ 1) + (_pos & 1); + else if (_pos >= str->end->_pos) + _pos = (str->end->_pos & ~ 1) + (_pos & 1); +} + +// A (slow) way to find the buffer a mark belongs to. + +edit_buffer * edit_mark::buffer() +{ + struct edit_mark *mark; + for (mark = this; mark->chain != NULL; mark = mark->chain) ; + // Assume that the last mark on the chain is the end_mark. + return (edit_buffer *)((char*)mark - offsetof(edit_buffer, end_mark)); +} + +edit_mark::~edit_mark() +{ + // Must unlink mark from chain of owning buffer + struct edit_buffer *buf = buffer(); + if (this == &buf->start_mark || this == &buf->end_mark) abort(); + edit_mark **ptr; + for (ptr = &buf->start_mark.chain; *ptr != this; ptr = &(*ptr)->chain) ; + *ptr = this->chain; +} + +int edit_string::length() const +{ + ptrdiff_t delta = end->ptr(buffer) - start->ptr(buffer); + if (end->ptr(buffer) <= buffer->gap_start() || + start->ptr(buffer) >= buffer->gap_end()) + return delta; + return delta - buffer->gap_size(); +} + +buf_char * edit_string::copy_bytes(int *lenp) const +{ + char *new_str; + int len1, len2; + buf_char *start1, *start2; + start1 = start->ptr(buffer); + if (end->ptr(buffer) <= buffer->gap_start() + || start->ptr(buffer) >= buffer->gap_end()) { + len1 = end->ptr(buffer) - start1; + len2 = 0; + start2 = NULL; // To avoid a warning from g++. + } + else { + len1 = buffer->gap_start() - start1; + start2 = buffer->gap_end(); + len2 = end->ptr(buffer) - start2; + } + new_str = (char*)malloc(len1 + len2 + 1); + memcpy(new_str, start1, len1); + if (len2 > 0) memcpy(new_str + len1, start2, len2); + new_str[len1+len2] = '\0'; + *lenp = len1+len2; + return new_str; +} + +// Replace the buf_chars in 'this' with ones from 'src'. +// Equivalent to deleting this, then inserting src, except tries +// to leave marks in place: Marks whose offset from the start +// of 'this' is less than 'src->length()' will still have the +// same offset in 'this' when done. + +void edit_string::assign(struct edit_string *src) +{ + edit_streambuf dst_file(this, ios::out); + if (buffer == src->buffer /*&& ???*/) { /* overly conservative */ + int src_len; + buf_char *new_str; + new_str = src->copy_bytes(&src_len); + dst_file.sputn(new_str, src_len); + free (new_str); + } else { + edit_streambuf src_file(src, ios::in); + for ( ; ; ) { + int ch = src_file.sbumpc(); + if (ch == EOF) break; + dst_file.sputc(ch); + } + } +} diff --git a/gnu/lib/libg++/libio/editbuf.h b/gnu/lib/libg++/libio/editbuf.h new file mode 100644 index 00000000000..d15758f257e --- /dev/null +++ b/gnu/lib/libg++/libio/editbuf.h @@ -0,0 +1,185 @@ +/* This is part of libio/iostream, providing -*- C++ -*- input/output. +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. + +Written by Per Bothner (bothner@cygnus.com). */ + +#ifndef _EDITBUF_H +#define _EDITBUF_H +#ifdef __GNUG__ +#pragma interface +#endif +#include <stdio.h> +#include <fstream.h> + +extern "C++" { +typedef unsigned long mark_pointer; +// At some point, it might be nice to parameterize this code +// in terms of buf_char. +typedef /*unsigned*/ char buf_char; + +// Logical pos from start of buffer (does not count gap). +typedef long buf_index; + +// Pos from start of buffer, possibly including gap_size. +typedef long buf_offset; + +#if 0 +struct buf_cookie { + FILE *file; + struct edit_string *str; + struct buf_cookie *next; + buf_index tell(); +}; +#endif + +struct edit_buffer; +struct edit_mark; + +// A edit_string is defined as the region between the 'start' and 'end' marks. +// Normally (always?) 'start->insert_before()' should be false, +// and 'end->insert_before()' should be true. + +struct edit_string { + struct edit_buffer *buffer; // buffer that 'start' and 'end' belong to + struct edit_mark *start, *end; + int length() const; // count of buf_chars currently in string + edit_string(struct edit_buffer *b, + struct edit_mark *ms, struct edit_mark *me) + { buffer = b; start = ms; end = me; } +/* Make a fresh, contiguous copy of the data in STR. + Assign length of STR to *LENP. + (Output has extra NUL at out[*LENP].) */ + buf_char *copy_bytes(int *lenp) const; +// FILE *open_file(char *mode); + void assign(struct edit_string *src); // copy bytes from src to this +}; + +struct edit_streambuf : public streambuf { + friend edit_buffer; + edit_string *str; + edit_streambuf* next; // Chain of edit_streambuf's for a edit_buffer. + short _mode; + edit_streambuf(edit_string* bstr, int mode); + ~edit_streambuf(); + virtual int underflow(); + virtual int overflow(int c = EOF); + virtual streampos seekoff(streamoff, _seek_dir, int mode=ios::in|ios::out); + void flush_to_buffer(); + void flush_to_buffer(edit_buffer* buffer); + int _inserting; + int inserting() { return _inserting; } + void inserting(int i) { _inserting = i; } +// int delete_chars(int count, char* cut_buf); Not implemented. + int truncate(); + int is_reading() { return gptr() != NULL; } + buf_char* current() { return is_reading() ? gptr() : pptr(); } + void set_current(char *p, int is_reading); + protected: + void disconnect_gap_from_file(edit_buffer* buffer); +}; + +// A 'edit_mark' indicates a position in a buffer. +// It is "attached" the text (rather than the offset). +// There are two kinds of mark, which have different behavior +// when text is inserted at the mark: +// If 'insert_before()' is true the mark will be adjusted to be +// *after* the new text. + +struct edit_mark { + struct edit_mark *chain; + mark_pointer _pos; + inline int insert_before() { return _pos & 1; } + inline unsigned long index_in_buffer(struct edit_buffer *) + { return _pos >> 1; } + inline buf_char *ptr(struct edit_buffer *buf); + buf_index tell(); + edit_mark() { } + edit_mark(struct edit_string *str, long delta); + edit_buffer *buffer(); + ~edit_mark(); +}; + +// A 'edit_buffer' consists of a sequence of buf_chars (the data), +// a list of edit_marks pointing into the data, and a list of FILEs +// also pointing into the data. +// A 'edit_buffer' coerced to a edit_string is the string of +// all the buf_chars in the buffer. + +// This implementation uses a conventional buffer gap (as in Emacs). +// The gap start is defined by de-referencing a (buf_char**). +// This is because sometimes a FILE is inserting into the buffer, +// so rather than having each putc adjust the gap, we use indirection +// to have the gap be defined as the write pointer of the FILE. +// (This assumes that putc adjusts a pointer (as in GNU's libc), not an index.) + +struct edit_buffer { + buf_char *data; /* == emacs buffer_text.p1+1 */ + buf_char *_gap_start; + edit_streambuf* _writer; // If non-NULL, currently writing stream + inline buf_char *gap_start() + { return _writer ? _writer->pptr() : _gap_start; } + buf_offset __gap_end_pos; // size of part 1 + size of gap + /* int gap; implicit: buf_size - size1 - size2 */ + int buf_size; + struct edit_streambuf *files; + struct edit_mark start_mark; + struct edit_mark end_mark; + edit_buffer(); + inline buf_offset gap_end_pos() { return __gap_end_pos; } + inline struct edit_mark *start_marker() { return &start_mark; } + inline struct edit_mark *end_marker() { return &end_mark; } +/* these should be protected, ultimately */ + buf_index tell(edit_mark*); + buf_index tell(buf_char*); + inline buf_char *gap_end() { return data + gap_end_pos(); } + inline int gap_size() { return gap_end() - gap_start(); } + inline int size1() { return gap_start() - data; } + inline int size2() { return buf_size - gap_end_pos(); } + inline struct edit_mark * mark_list() { return &start_mark; } + void make_gap (buf_offset); + void move_gap (buf_offset pos); + void move_gap (buf_char *pos) { move_gap(pos - data); } + void gap_left (int pos); + void gap_right (int pos); + void adjust_markers(mark_pointer low, mark_pointer high, + int amount, buf_char *old_data); + void delete_range(buf_index from, buf_index to); + void delete_range(struct edit_mark *start, struct edit_mark *end); +}; + +extern buf_char * bstr_copy(struct edit_string *str, int *lenp); + +// Convert a edit_mark to a (buf_char*) + +inline buf_char *edit_mark::ptr(struct edit_buffer *buf) + { return buf->data + index_in_buffer(buf); } + +inline void edit_streambuf::flush_to_buffer() +{ + edit_buffer* buffer = str->buffer; + if (buffer->_writer == this) flush_to_buffer(buffer); +} +} // extern "C++" +#endif /* !_EDITBUF_H*/ + diff --git a/gnu/lib/libg++/libio/filebuf.cc b/gnu/lib/libg++/libio/filebuf.cc new file mode 100644 index 00000000000..8f4bdc8a020 --- /dev/null +++ b/gnu/lib/libg++/libio/filebuf.cc @@ -0,0 +1,198 @@ +/* This is part of libio/iostream, providing -*- C++ -*- input/output. +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). */ + +#include "iostreamP.h" +#include <sys/types.h> +#include <sys/stat.h> +#include <fcntl.h> +#include <errno.h> +#include "builtinbuf.h" + +void filebuf::init() +{ + _IO_file_init(this); +} + +filebuf::filebuf() +{ + _IO_file_init(this); +} + +#if !_IO_UNIFIED_JUMPTABLES +/* This is like "new filebuf()", but it uses the _IO_file_jump jumptable, + for eficiency. */ + +filebuf* filebuf::__new() +{ + filebuf *fb = new filebuf; + _IO_JUMPS(fb) = &_IO_file_jumps; + fb->_vtable() = builtinbuf_vtable; + return fb; +} +#endif + +filebuf::filebuf(int fd) +{ + _IO_file_init(this); + _IO_file_attach(this, fd); +} + +filebuf::filebuf(int fd, char* p, int len) +{ + _IO_file_init(this); + _IO_file_attach(this, fd); + setbuf(p, len); +} + +filebuf::~filebuf() +{ + if (_IO_file_is_open(this)) + { + _IO_do_flush (this); + if (!(xflags() & _IO_DELETE_DONT_CLOSE)) + _IO_SYSCLOSE (this); + } +} + +filebuf* filebuf::open(const char *filename, ios::openmode mode, int prot) +{ + if (_IO_file_is_open (this)) + return NULL; + int posix_mode; + int read_write; + if (mode & ios::app) + mode |= ios::out; + if ((mode & (ios::in|ios::out)) == (ios::in|ios::out)) { + posix_mode = O_RDWR; + read_write = 0; + } + else if (mode & ios::out) + posix_mode = O_WRONLY, read_write = _IO_NO_READS; + else if (mode & (int)ios::in) + posix_mode = O_RDONLY, read_write = _IO_NO_WRITES; + else + posix_mode = 0, read_write = _IO_NO_READS+_IO_NO_WRITES; + if ((mode & (int)ios::trunc) || mode == (int)ios::out) + posix_mode |= O_TRUNC; + if (mode & ios::app) + posix_mode |= O_APPEND, read_write |= _IO_IS_APPENDING; + if (!(mode & (int)ios::nocreate) && mode != ios::in) + posix_mode |= O_CREAT; + if (mode & (int)ios::noreplace) + posix_mode |= O_EXCL; + int fd = ::open(filename, posix_mode, prot); + if (fd < 0) + return NULL; + _fileno = fd; + xsetflags(read_write, _IO_NO_READS+_IO_NO_WRITES+_IO_IS_APPENDING); + if (mode & (ios::ate|ios::app)) { + if (pubseekoff(0, ios::end) == EOF) + return NULL; + } + _IO_link_in(this); + return this; +} + +filebuf* filebuf::open(const char *filename, const char *mode) +{ + return (filebuf*)_IO_file_fopen(this, filename, mode); +} + +filebuf* filebuf::attach(int fd) +{ + return (filebuf*)_IO_file_attach(this, fd); +} + +streambuf* filebuf::setbuf(char* p, int len) +{ + return (streambuf*)_IO_file_setbuf (this, p, len); +} + +int filebuf::doallocate() { return _IO_file_doallocate(this); } + +int filebuf::overflow(int c) +{ + return _IO_file_overflow(this, c); +} + +int filebuf::underflow() +{ + return _IO_file_underflow(this); +} + +int filebuf::sync() +{ + return _IO_file_sync(this); +} + +streampos filebuf::seekoff(streamoff offset, _seek_dir dir, int mode) +{ + return _IO_file_seekoff (this, offset, dir, mode); +} + +filebuf* filebuf::close() +{ + return (_IO_file_close_it(this) ? (filebuf*)NULL : this); +} + +streamsize filebuf::sys_read(char* buf, streamsize size) +{ + return _IO_file_read(this, buf, size); +} + +streampos filebuf::sys_seek(streamoff offset, _seek_dir dir) +{ + return _IO_file_seek(this, offset, dir); +} + +streamsize filebuf::sys_write(const char *buf, streamsize n) +{ + return _IO_file_write (this, buf, n); +} + +int filebuf::sys_stat(void* st) +{ + return _IO_file_stat (this, st); +} + +int filebuf::sys_close() +{ + return _IO_file_close (this); +} + +streamsize filebuf::xsputn(const char *s, streamsize n) +{ + return _IO_file_xsputn(this, s, n); +} + +streamsize filebuf::xsgetn(char *s, streamsize n) +{ + // FIXME: OPTIMIZE THIS (specifically, when unbuffered()). + return streambuf::xsgetn(s, n); +} + +// Non-ANSI AT&T-ism: Default open protection. +const int filebuf::openprot = 0644; diff --git a/gnu/lib/libg++/libio/filedoalloc.c b/gnu/lib/libg++/libio/filedoalloc.c new file mode 100644 index 00000000000..6218135eaed --- /dev/null +++ b/gnu/lib/libg++/libio/filedoalloc.c @@ -0,0 +1,104 @@ +/* +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> +#include <unistd.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/gnu/lib/libg++/libio/fileops.c b/gnu/lib/libg++/libio/fileops.c new file mode 100644 index 00000000000..89381ec6997 --- /dev/null +++ b/gnu/lib/libg++/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/gnu/lib/libg++/libio/floatconv.c b/gnu/lib/libg++/libio/floatconv.c new file mode 100644 index 00000000000..a6183f9e9de --- /dev/null +++ b/gnu/lib/libg++/libio/floatconv.c @@ -0,0 +1,2349 @@ +/* +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. */ + +#include <libioP.h> +#ifdef _IO_USE_DTOA +/**************************************************************** + * + * The author of this software is David M. Gay. + * + * Copyright (c) 1991 by AT&T. + * + * Permission to use, copy, modify, and distribute this software for any + * purpose without fee is hereby granted, provided that this entire notice + * is included in all copies of any software which is or includes a copy + * or modification of this software and in all copies of the supporting + * documentation for such software. + * + * THIS SOFTWARE IS BEING PROVIDED "AS IS", WITHOUT ANY EXPRESS OR IMPLIED + * WARRANTY. IN PARTICULAR, NEITHER THE AUTHOR NOR AT&T MAKES ANY + * REPRESENTATION OR WARRANTY OF ANY KIND CONCERNING THE MERCHANTABILITY + * OF THIS SOFTWARE OR ITS FITNESS FOR ANY PARTICULAR PURPOSE. + * + ***************************************************************/ + +/* Some cleaning up by Per Bothner, bothner@cygnus.com, 1992, 1993. + Re-written to not need static variables + (except result, result_k, HIWORD, LOWORD). */ + +/* Please send bug reports to + David M. Gay + AT&T Bell Laboratories, Room 2C-463 + 600 Mountain Avenue + Murray Hill, NJ 07974-2070 + U.S.A. + dmg@research.att.com or research!dmg + */ + +/* strtod for IEEE-, VAX-, and IBM-arithmetic machines. + * + * This strtod returns a nearest machine number to the input decimal + * string (or sets errno to ERANGE). With IEEE arithmetic, ties are + * broken by the IEEE round-even rule. Otherwise ties are broken by + * biased rounding (add half and chop). + * + * Inspired loosely by William D. Clinger's paper "How to Read Floating + * Point Numbers Accurately" [Proc. ACM SIGPLAN '90, pp. 92-101]. + * + * Modifications: + * + * 1. We only require IEEE, IBM, or VAX double-precision + * arithmetic (not IEEE double-extended). + * 2. We get by with floating-point arithmetic in a case that + * Clinger missed -- when we're computing d * 10^n + * for a small integer d and the integer n is not too + * much larger than 22 (the maximum integer k for which + * we can represent 10^k exactly), we may be able to + * compute (d*10^k) * 10^(e-k) with just one roundoff. + * 3. Rather than a bit-at-a-time adjustment of the binary + * result in the hard case, we use floating-point + * arithmetic to determine the adjustment to within + * one bit; only in really hard cases do we need to + * compute a second residual. + * 4. Because of 3., we don't need a large table of powers of 10 + * for ten-to-e (just some small tables, e.g. of 10^k + * for 0 <= k <= 22). + */ + +/* + * #define IEEE_8087 for IEEE-arithmetic machines where the least + * significant byte has the lowest address. + * #define IEEE_MC68k for IEEE-arithmetic machines where the most + * significant byte has the lowest address. + * #define Sudden_Underflow for IEEE-format machines without gradual + * underflow (i.e., that flush to zero on underflow). + * #define IBM for IBM mainframe-style floating-point arithmetic. + * #define VAX for VAX-style floating-point arithmetic. + * #define Unsigned_Shifts if >> does treats its left operand as unsigned. + * #define No_leftright to omit left-right logic in fast floating-point + * computation of dtoa. + * #define Check_FLT_ROUNDS if FLT_ROUNDS can assume the values 2 or 3. + * #define RND_PRODQUOT to use rnd_prod and rnd_quot (assembly routines + * that use extended-precision instructions to compute rounded + * products and quotients) with IBM. + * #define ROUND_BIASED for IEEE-format with biased rounding. + * #define Inaccurate_Divide for IEEE-format with correctly rounded + * products but inaccurate quotients, e.g., for Intel i860. + * #define KR_headers for old-style C function headers. + */ + +#ifdef DEBUG +#include <stdio.h> +#define Bug(x) {fprintf(stderr, "%s\n", x); exit(1);} +#endif + +#ifdef __STDC__ +#include <stdlib.h> +#include <string.h> +#include <float.h> +#define CONST const +#else +#define CONST +#define KR_headers + +/* In this case, we assume IEEE floats. */ +#define FLT_ROUNDS 1 +#define FLT_RADIX 2 +#define DBL_MANT_DIG 53 +#define DBL_DIG 15 +#define DBL_MAX_10_EXP 308 +#define DBL_MAX_EXP 1024 +#endif + +#include <errno.h> +#ifndef __MATH_H__ +#include <math.h> +#endif + +#ifdef Unsigned_Shifts +#define Sign_Extend(a,b) if (b < 0) a |= 0xffff0000; +#else +#define Sign_Extend(a,b) /*no-op*/ +#endif + +#if defined(__i386__) || defined(__i860__) || defined(clipper) +#define IEEE_8087 +#endif +#if defined(MIPSEL) || defined(__alpha__) +#define IEEE_8087 +#endif +#if defined(__sparc__) || defined(sparc) || defined(MIPSEB) +#define IEEE_MC68k +#endif + +#if defined(IEEE_8087) + defined(IEEE_MC68k) + defined(VAX) + defined(IBM) != 1 + +#if FLT_RADIX==16 +#define IBM +#else +#if DBL_MANT_DIG==56 +#define VAX +#else +#if DBL_MANT_DIG==53 && DBL_MAX_10_EXP==308 +#define IEEE_Unknown +#else +Exactly one of IEEE_8087, IEEE_MC68k, VAX, or IBM should be defined. +#endif +#endif +#endif +#endif + +typedef _G_uint32_t unsigned32; + +union doubleword { + double d; + unsigned32 u[2]; +}; + +#ifdef IEEE_8087 +#define HIWORD 1 +#define LOWORD 0 +#define TEST_ENDIANNESS /* nothing */ +#else +#if defined(IEEE_MC68k) +#define HIWORD 0 +#define LOWORD 1 +#define TEST_ENDIANNESS /* nothing */ +#else +static int HIWORD = -1, LOWORD; +static void test_endianness() +{ + union doubleword dw; + dw.d = 10; + if (dw.u[0] != 0) /* big-endian */ + HIWORD=0, LOWORD=1; + else + HIWORD=1, LOWORD=0; +} +#define TEST_ENDIANNESS if (HIWORD<0) test_endianness(); +#endif +#endif + +#if 0 +union doubleword _temp; +#endif +#ifdef __GNUC__ +#define word0(x) ({ union doubleword _du; _du.d = (x); _du.u[HIWORD]; }) +#define word1(x) ({ union doubleword _du; _du.d = (x); _du.u[LOWORD]; }) +#define setword0(D,W) \ + ({ union doubleword _du; _du.d = (D); _du.u[HIWORD]=(W); (D)=_du.d; }) +#define setword1(D,W) \ + ({ union doubleword _du; _du.d = (D); _du.u[LOWORD]=(W); (D)=_du.d; }) +#define setwords(D,W0,W1) ({ union doubleword _du; \ + _du.u[HIWORD]=(W0); _du.u[LOWORD]=(W1); (D)=_du.d; }) +#define addword0(D,W) \ + ({ union doubleword _du; _du.d = (D); _du.u[HIWORD]+=(W); (D)=_du.d; }) +#else +#define word0(x) ((unsigned32 *)&x)[HIWORD] +#define word1(x) ((unsigned32 *)&x)[LOWORD] +#define setword0(D,W) word0(D) = (W) +#define setword1(D,W) word1(D) = (W) +#define setwords(D,W0,W1) (setword0(D,W0),setword1(D,W1)) +#define addword0(D,X) (word0(D) += (X)) +#endif + +/* The following definition of Storeinc is appropriate for MIPS processors. */ +#if defined(IEEE_8087) + defined(VAX) +#define Storeinc(a,b,c) (((unsigned short *)a)[1] = (unsigned short)b, \ +((unsigned short *)a)[0] = (unsigned short)c, a++) +#else +#if defined(IEEE_MC68k) +#define Storeinc(a,b,c) (((unsigned short *)a)[0] = (unsigned short)b, \ +((unsigned short *)a)[1] = (unsigned short)c, a++) +#else +#define Storeinc(a,b,c) (*a++ = b << 16 | c & 0xffff) +#endif +#endif + +/* #define P DBL_MANT_DIG */ +/* Ten_pmax = floor(P*log(2)/log(5)) */ +/* Bletch = (highest power of 2 < DBL_MAX_10_EXP) / 16 */ +/* Quick_max = floor((P-1)*log(FLT_RADIX)/log(10) - 1) */ +/* Int_max = floor(P*log(FLT_RADIX)/log(10) - 1) */ + +#if defined(IEEE_8087) + defined(IEEE_MC68k) + defined(IEEE_Unknown) +#define Exp_shift 20 +#define Exp_shift1 20 +#define Exp_msk1 0x100000 +#define Exp_msk11 0x100000 +#define Exp_mask 0x7ff00000 +#define P 53 +#define Bias 1023 +#define IEEE_Arith +#define Emin (-1022) +#define Exp_1 0x3ff00000 +#define Exp_11 0x3ff00000 +#define Ebits 11 +#define Frac_mask 0xfffff +#define Frac_mask1 0xfffff +#define Ten_pmax 22 +#define Bletch 0x10 +#define Bndry_mask 0xfffff +#define Bndry_mask1 0xfffff +#define LSB 1 +#define Sign_bit 0x80000000 +#define Log2P 1 +#define Tiny0 0 +#define Tiny1 1 +#define Quick_max 14 +#define Int_max 14 +#define Infinite(x) (word0(x) == 0x7ff00000) /* sufficient test for here */ +#else +#undef Sudden_Underflow +#define Sudden_Underflow +#ifdef IBM +#define Exp_shift 24 +#define Exp_shift1 24 +#define Exp_msk1 0x1000000 +#define Exp_msk11 0x1000000 +#define Exp_mask 0x7f000000 +#define P 14 +#define Bias 65 +#define Exp_1 0x41000000 +#define Exp_11 0x41000000 +#define Ebits 8 /* exponent has 7 bits, but 8 is the right value in b2d */ +#define Frac_mask 0xffffff +#define Frac_mask1 0xffffff +#define Bletch 4 +#define Ten_pmax 22 +#define Bndry_mask 0xefffff +#define Bndry_mask1 0xffffff +#define LSB 1 +#define Sign_bit 0x80000000 +#define Log2P 4 +#define Tiny0 0x100000 +#define Tiny1 0 +#define Quick_max 14 +#define Int_max 15 +#else /* VAX */ +#define Exp_shift 23 +#define Exp_shift1 7 +#define Exp_msk1 0x80 +#define Exp_msk11 0x800000 +#define Exp_mask 0x7f80 +#define P 56 +#define Bias 129 +#define Exp_1 0x40800000 +#define Exp_11 0x4080 +#define Ebits 8 +#define Frac_mask 0x7fffff +#define Frac_mask1 0xffff007f +#define Ten_pmax 24 +#define Bletch 2 +#define Bndry_mask 0xffff007f +#define Bndry_mask1 0xffff007f +#define LSB 0x10000 +#define Sign_bit 0x8000 +#define Log2P 1 +#define Tiny0 0x80 +#define Tiny1 0 +#define Quick_max 15 +#define Int_max 15 +#endif +#endif + +#ifndef IEEE_Arith +#define ROUND_BIASED +#endif + +#ifdef RND_PRODQUOT +#define rounded_product(a,b) a = rnd_prod(a, b) +#define rounded_quotient(a,b) a = rnd_quot(a, b) +extern double rnd_prod(double, double), rnd_quot(double, double); +#else +#define rounded_product(a,b) a *= b +#define rounded_quotient(a,b) a /= b +#endif + +#define Big0 (Frac_mask1 | Exp_msk1*(DBL_MAX_EXP+Bias-1)) +#define Big1 0xffffffff + +#define Kmax 15 + +/* (1<<BIGINT_MINIMUM_K) is the minimum number of words to allocate + in a Bigint. dtoa usually manages with 1<<2, and has not been + known to need more than 1<<3. */ + +#define BIGINT_MINIMUM_K 3 + +struct Bigint { + struct Bigint *next; + int k; /* Parameter given to Balloc(k) */ + int maxwds; /* Allocated space: equals 1<<k. */ + short on_stack; /* 1 if stack-allocated. */ + short sign; /* 0 if value is positive or zero; 1 if negative. */ + int wds; /* Current length. */ + unsigned32 x[1<<BIGINT_MINIMUM_K]; /* Actually: x[maxwds] */ +}; + +#define BIGINT_HEADER_SIZE \ + (sizeof(Bigint) - (1<<BIGINT_MINIMUM_K) * sizeof(unsigned32)) + +typedef struct Bigint Bigint; + +/* Initialize a stack-allocated Bigint. */ + +static Bigint * +Binit +#ifdef KR_headers + (v) Bigint *v; +#else + (Bigint *v) +#endif +{ + v->on_stack = 1; + v->k = BIGINT_MINIMUM_K; + v->maxwds = 1 << BIGINT_MINIMUM_K; + v->sign = v->wds = 0; + return v; +} + +/* Allocate a Bigint with '1<<k' big digits. */ + +static Bigint * +Balloc +#ifdef KR_headers + (k) int k; +#else + (int k) +#endif +{ + int x; + Bigint *rv; + + if (k < BIGINT_MINIMUM_K) + k = BIGINT_MINIMUM_K; + + x = 1 << k; + rv = (Bigint *) + malloc(BIGINT_HEADER_SIZE + x * sizeof(unsigned32)); + rv->k = k; + rv->maxwds = x; + rv->sign = rv->wds = 0; + rv->on_stack = 0; + return rv; +} + +static void +Bfree +#ifdef KR_headers + (v) Bigint *v; +#else + (Bigint *v) +#endif +{ + if (v && !v->on_stack) + free (v); +} + +static void +Bcopy +#ifdef KR_headers + (x, y) Bigint *x, *y; +#else + (Bigint *x, Bigint *y) +#endif +{ + register unsigned32 *xp, *yp; + register int i = y->wds; + x->sign = y->sign; + x->wds = i; + for (xp = x->x, yp = y->x; --i >= 0; ) + *xp++ = *yp++; +} + +/* Make sure b has room for at least 1<<k big digits. */ + +static Bigint * +Brealloc +#ifdef KR_headers + (b, k) Bigint *b; int k; +#else + (Bigint * b, int k) +#endif +{ + if (b == NULL) + return Balloc(k); + if (b->k >= k) + return b; + else + { + Bigint *rv = Balloc (k); + Bcopy(rv, b); + Bfree(b); + return rv; + } +} + +/* Return b*m+a. b is modified. + Assumption: 0xFFFF*m+a fits in 32 bits. */ + +static Bigint * +multadd +#ifdef KR_headers + (b, m, a) Bigint *b; int m, a; +#else + (Bigint *b, int m, int a) +#endif +{ + int i, wds; + unsigned32 *x, y; + unsigned32 xi, z; + + wds = b->wds; + x = b->x; + i = 0; + do { + xi = *x; + y = (xi & 0xffff) * m + a; + z = (xi >> 16) * m + (y >> 16); + a = (int)(z >> 16); + *x++ = (z << 16) + (y & 0xffff); + } + while(++i < wds); + if (a) { + if (wds >= b->maxwds) + b = Brealloc(b, b->k+1); + b->x[wds++] = a; + b->wds = wds; + } + return b; + } + +static Bigint * +s2b +#ifdef KR_headers + (result, s, nd0, nd, y9) + Bigint *result; CONST char *s; int nd0, nd; unsigned32 y9; +#else + (Bigint *result, CONST char *s, int nd0, int nd, unsigned32 y9) +#endif +{ + int i, k; + _G_int32_t x, y; + + x = (nd + 8) / 9; + for(k = 0, y = 1; x > y; y <<= 1, k++) ; + result = Brealloc(result, k); + result->x[0] = y9; + result->wds = 1; + + i = 9; + if (9 < nd0) + { + s += 9; + do + result = multadd(result, 10, *s++ - '0'); + while (++i < nd0); + s++; + } + else + s += 10; + for(; i < nd; i++) + result = multadd(result, 10, *s++ - '0'); + return result; +} + +static int +hi0bits +#ifdef KR_headers + (x) register unsigned32 x; +#else + (register unsigned32 x) +#endif +{ + register int k = 0; + + if (!(x & 0xffff0000)) { + k = 16; + x <<= 16; + } + if (!(x & 0xff000000)) { + k += 8; + x <<= 8; + } + if (!(x & 0xf0000000)) { + k += 4; + x <<= 4; + } + if (!(x & 0xc0000000)) { + k += 2; + x <<= 2; + } + if (!(x & 0x80000000)) { + k++; + if (!(x & 0x40000000)) + return 32; + } + return k; + } + +static int +lo0bits +#ifdef KR_headers + (y) unsigned32 *y; +#else + (unsigned32 *y) +#endif +{ + register int k; + register unsigned32 x = *y; + + if (x & 7) { + if (x & 1) + return 0; + if (x & 2) { + *y = x >> 1; + return 1; + } + *y = x >> 2; + return 2; + } + k = 0; + if (!(x & 0xffff)) { + k = 16; + x >>= 16; + } + if (!(x & 0xff)) { + k += 8; + x >>= 8; + } + if (!(x & 0xf)) { + k += 4; + x >>= 4; + } + if (!(x & 0x3)) { + k += 2; + x >>= 2; + } + if (!(x & 1)) { + k++; + x >>= 1; + if (!x & 1) + return 32; + } + *y = x; + return k; + } + +static Bigint * +i2b +#ifdef KR_headers + (result, i) Bigint *result; int i; +#else + (Bigint* result, int i) +#endif +{ + result = Brealloc(result, 1); + result->x[0] = i; + result->wds = 1; + return result; +} + +/* Do: c = a * b. */ + +static Bigint * +mult +#ifdef KR_headers + (c, a, b) Bigint *a, *b, *c; +#else + (Bigint *c, Bigint *a, Bigint *b) +#endif +{ + int k, wa, wb, wc; + unsigned32 carry, y, z; + unsigned32 *x, *xa, *xae, *xb, *xbe, *xc, *xc0; + unsigned32 z2; + if (a->wds < b->wds) { + Bigint *tmp = a; + a = b; + b = tmp; + } + k = a->k; + wa = a->wds; + wb = b->wds; + wc = wa + wb; + if (wc > a->maxwds) + k++; + c = Brealloc(c, k); + for(x = c->x, xa = x + wc; x < xa; x++) + *x = 0; + xa = a->x; + xae = xa + wa; + xb = b->x; + xbe = xb + wb; + xc0 = c->x; + for(; xb < xbe; xb++, xc0++) { + if ((y = *xb & 0xffff)) { + x = xa; + xc = xc0; + carry = 0; + do { + z = (*x & 0xffff) * y + (*xc & 0xffff) + carry; + carry = z >> 16; + z2 = (*x++ >> 16) * y + (*xc >> 16) + carry; + carry = z2 >> 16; + Storeinc(xc, z2, z); + } + while(x < xae); + *xc = carry; + } + if ((y = *xb >> 16)) { + x = xa; + xc = xc0; + carry = 0; + z2 = *xc; + do { + z = (*x & 0xffff) * y + (*xc >> 16) + carry; + carry = z >> 16; + Storeinc(xc, z, z2); + z2 = (*x++ >> 16) * y + (*xc & 0xffff) + carry; + carry = z2 >> 16; + } + while(x < xae); + *xc = z2; + } + } + for(xc0 = c->x, xc = xc0 + wc; wc > 0 && !*--xc; --wc) ; + c->wds = wc; + return c; + } + +/* Returns b*(5**k). b is modified. */ +/* Re-written by Per Bothner to not need a static list. */ + +static Bigint * +pow5mult +#ifdef KR_headers + (b, k) Bigint *b; int k; +#else + (Bigint *b, int k) +#endif +{ + static int p05[6] = { 5, 25, 125, 625, 3125, 15625 }; + + for (; k > 6; k -= 6) + b = multadd(b, 15625, 0); /* b *= 5**6 */ + if (k == 0) + return b; + else + return multadd(b, p05[k-1], 0); +} + +/* Re-written by Per Bothner so shift can be in place. */ + +static Bigint * +lshift +#ifdef KR_headers + (b, k) Bigint *b; int k; +#else + (Bigint *b, int k) +#endif +{ + int i; + unsigned32 *x, *x1, *xe; + int old_wds = b->wds; + int n = k >> 5; + int k1 = b->k; + int n1 = n + old_wds + 1; + + if (k == 0) + return b; + + for(i = b->maxwds; n1 > i; i <<= 1) + k1++; + b = Brealloc(b, k1); + + xe = b->x; /* Source limit */ + x = xe + old_wds; /* Source pointer */ + x1 = x + n; /* Destination pointer */ + if (k &= 0x1f) { + int k1 = 32 - k; + unsigned32 z = *--x; + if ((*x1 = (z >> k1)) != 0) { + ++n1; + } + while (x > xe) { + unsigned32 w = *--x; + *--x1 = (z << k) | (w >> k1); + z = w; + } + *--x1 = z << k; + } + else + do { + *--x1 = *--x; + } while(x > xe); + while (x1 > xe) + *--x1 = 0; + b->wds = n1 - 1; + return b; +} + +static int +cmp +#ifdef KR_headers + (a, b) Bigint *a, *b; +#else + (Bigint *a, Bigint *b) +#endif +{ + unsigned32 *xa, *xa0, *xb, *xb0; + int i, j; + + i = a->wds; + j = b->wds; +#ifdef DEBUG + if (i > 1 && !a->x[i-1]) + Bug("cmp called with a->x[a->wds-1] == 0"); + if (j > 1 && !b->x[j-1]) + Bug("cmp called with b->x[b->wds-1] == 0"); +#endif + if (i -= j) + return i; + xa0 = a->x; + xa = xa0 + j; + xb0 = b->x; + xb = xb0 + j; + for(;;) { + if (*--xa != *--xb) + return *xa < *xb ? -1 : 1; + if (xa <= xa0) + break; + } + return 0; + } + +/* Do: c = a-b. */ + +static Bigint * +diff +#ifdef KR_headers + (c, a, b) Bigint *c, *a, *b; +#else + (Bigint *c, Bigint *a, Bigint *b) +#endif +{ + int i, wa, wb; + _G_int32_t borrow, y; /* We need signed shifts here. */ + unsigned32 *xa, *xae, *xb, *xbe, *xc; + _G_int32_t z; + + i = cmp(a,b); + if (!i) { + c = Brealloc(c, 0); + c->wds = 1; + c->x[0] = 0; + return c; + } + if (i < 0) { + Bigint *tmp = a; + a = b; + b = tmp; + i = 1; + } + else + i = 0; + c = Brealloc(c, a->k); + c->sign = i; + wa = a->wds; + xa = a->x; + xae = xa + wa; + wb = b->wds; + xb = b->x; + xbe = xb + wb; + xc = c->x; + borrow = 0; + do { + y = (*xa & 0xffff) - (*xb & 0xffff) + borrow; + borrow = y >> 16; + Sign_Extend(borrow, y); + z = (*xa++ >> 16) - (*xb++ >> 16) + borrow; + borrow = z >> 16; + Sign_Extend(borrow, z); + Storeinc(xc, z, y); + } + while(xb < xbe); + while(xa < xae) { + y = (*xa & 0xffff) + borrow; + borrow = y >> 16; + Sign_Extend(borrow, y); + z = (*xa++ >> 16) + borrow; + borrow = z >> 16; + Sign_Extend(borrow, z); + Storeinc(xc, z, y); + } + while(!*--xc) + wa--; + c->wds = wa; + return c; + } + +static double +ulp +#ifdef KR_headers + (x) double x; +#else + (double x) +#endif +{ + register _G_int32_t L; + double a; + + L = (word0(x) & Exp_mask) - (P-1)*Exp_msk1; +#ifndef Sudden_Underflow + if (L > 0) { +#endif +#ifdef IBM + L |= Exp_msk1 >> 4; +#endif + setwords(a, L, 0); +#ifndef Sudden_Underflow + } + else { + L = -L >> Exp_shift; + if (L < Exp_shift) + setwords(a, 0x80000 >> L, 0); + else { + L -= Exp_shift; + setwords(a, 0, L >= 31 ? 1 : 1 << (31 - L)); + } + } +#endif + return a; + } + +static double +b2d +#ifdef KR_headers + (a, e) Bigint *a; int *e; +#else + (Bigint *a, int *e) +#endif +{ + unsigned32 *xa, *xa0, w, y, z; + int k; + double d; + unsigned32 d0, d1; + + xa0 = a->x; + xa = xa0 + a->wds; + y = *--xa; +#ifdef DEBUG + if (!y) Bug("zero y in b2d"); +#endif + k = hi0bits(y); + *e = 32 - k; + if (k < Ebits) { + d0 = Exp_1 | y >> (Ebits - k); + w = xa > xa0 ? *--xa : 0; + d1 = y << ((32-Ebits) + k) | w >> (Ebits - k); + goto ret_d; + } + z = xa > xa0 ? *--xa : 0; + if (k -= Ebits) { + d0 = Exp_1 | y << k | z >> (32 - k); + y = xa > xa0 ? *--xa : 0; + d1 = z << k | y >> (32 - k); + } + else { + d0 = Exp_1 | y; + d1 = z; + } + ret_d: +#ifdef VAX + setwords(d, d0 >> 16 | d0 << 16, d1 >> 16 | d1 << 16); +#else + setwords (d, d0, d1); +#endif + return d; + } + +static Bigint * +d2b +#ifdef KR_headers + (result, d, e, bits) Bigint *result; double d; int *e, *bits; +#else + (Bigint *result, double d, int *e, int *bits) +#endif +{ + int de, i, k; + unsigned32 *x, y, z; + unsigned32 d0, d1; +#ifdef VAX + d0 = word0(d) >> 16 | word0(d) << 16; + d1 = word1(d) >> 16 | word1(d) << 16; +#else + d0 = word0(d); + d1 = word1(d); +#endif + + result = Brealloc(result, 1); + x = result->x; + + z = d0 & Frac_mask; + d0 &= 0x7fffffff; /* clear sign bit, which we ignore */ + + de = (int)(d0 >> Exp_shift); /* The exponent part of d. */ + + /* Put back the suppressed high-order bit, if normalized. */ +#ifndef IBM +#ifndef Sudden_Underflow + if (de) +#endif + z |= Exp_msk11; +#endif + + if ((y = d1)) { + if ((k = lo0bits(&y))) { + x[0] = y | z << (32 - k); + z >>= k; + } + else + x[0] = y; + i = result->wds = (x[1] = z) ? 2 : 1; + } + else { +#ifdef DEBUG + if (!z) + Bug("Zero passed to d2b"); +#endif + k = lo0bits(&z); + x[0] = z; + i = result->wds = 1; + k += 32; + } +#ifndef Sudden_Underflow + if (de) { +#endif +#ifdef IBM + *e = (de - Bias - (P-1) << 2) + k; + *bits = 4*P + 8 - k - hi0bits(word0(d) & Frac_mask); +#else + *e = de - Bias - (P-1) + k; + *bits = P - k; +#endif +#ifndef Sudden_Underflow + } + else { + *e = de - Bias - (P-1) + 1 + k; + *bits = 32*i - hi0bits(x[i-1]); + } +#endif + return result; + } + +static double +ratio +#ifdef KR_headers + (a, b) Bigint *a, *b; +#else + (Bigint *a, Bigint *b) +#endif +{ + double da, db; + int k, ka, kb; + + da = b2d(a, &ka); + db = b2d(b, &kb); + k = ka - kb + 32*(a->wds - b->wds); +#ifdef IBM + if (k > 0) { + addword0(da, (k >> 2)*Exp_msk1); + if (k &= 3) + da *= 1 << k; + } + else { + k = -k; + addword0(db,(k >> 2)*Exp_msk1); + if (k &= 3) + db *= 1 << k; + } +#else + if (k > 0) + addword0(da, k*Exp_msk1); + else { + k = -k; + addword0(db, k*Exp_msk1); + } +#endif + return da / db; + } + +static CONST double +tens[] = { + 1e0, 1e1, 1e2, 1e3, 1e4, 1e5, 1e6, 1e7, 1e8, 1e9, + 1e10, 1e11, 1e12, 1e13, 1e14, 1e15, 1e16, 1e17, 1e18, 1e19, + 1e20, 1e21, 1e22 +#ifdef VAX + , 1e23, 1e24 +#endif + }; + +#ifdef IEEE_Arith +static CONST double bigtens[] = { 1e16, 1e32, 1e64, 1e128, 1e256 }; +static CONST double tinytens[] = { 1e-16, 1e-32, 1e-64, 1e-128, 1e-256 }; +#define n_bigtens 5 +#else +#ifdef IBM +static CONST double bigtens[] = { 1e16, 1e32, 1e64 }; +static CONST double tinytens[] = { 1e-16, 1e-32, 1e-64 }; +#define n_bigtens 3 +#else +static CONST double bigtens[] = { 1e16, 1e32 }; +static CONST double tinytens[] = { 1e-16, 1e-32 }; +#define n_bigtens 2 +#endif +#endif + + double +_IO_strtod +#ifdef KR_headers + (s00, se) CONST char *s00; char **se; +#else + (CONST char *s00, char **se) +#endif +{ + int bb2, bb5, bbe, bd2, bd5, bbbits, bs2, c, dsign, + e, e1, esign, i, j, k, nd, nd0, nf, nz, nz0, sign; + CONST char *s, *s0, *s1; + double aadj, aadj1, adj, rv, rv0; + _G_int32_t L; + unsigned32 y, z; + Bigint _bb, _b_avail, _bd, _bd0, _bs, _delta; + Bigint *bb = Binit(&_bb); + Bigint *bd = Binit(&_bd); + Bigint *bd0 = Binit(&_bd0); + Bigint *bs = Binit(&_bs); + Bigint *b_avail = Binit(&_b_avail); + Bigint *delta = Binit(&_delta); + + TEST_ENDIANNESS; + sign = nz0 = nz = 0; + rv = 0.; + for(s = s00;;s++) switch(*s) { + case '-': + sign = 1; + /* no break */ + case '+': + if (*++s) + goto break2; + /* no break */ + case 0: + /* "+" and "-" should be reported as an error? */ + sign = 0; + s = s00; + goto ret; + case '\t': + case '\n': + case '\v': + case '\f': + case '\r': + case ' ': + continue; + default: + goto break2; + } + break2: + if (*s == '0') { + nz0 = 1; + while(*++s == '0') ; + if (!*s) + goto ret; + } + s0 = s; + y = z = 0; + for(nd = nf = 0; (c = *s) >= '0' && c <= '9'; nd++, s++) + if (nd < 9) + y = 10*y + c - '0'; + else if (nd < 16) + z = 10*z + c - '0'; + nd0 = nd; + if (c == '.') { + c = *++s; + if (!nd) { + for(; c == '0'; c = *++s) + nz++; + if (c > '0' && c <= '9') { + s0 = s; + nf += nz; + nz = 0; + goto have_dig; + } + goto dig_done; + } + for(; c >= '0' && c <= '9'; c = *++s) { + have_dig: + nz++; + if (c -= '0') { + nf += nz; + for(i = 1; i < nz; i++) + if (nd++ < 9) + y *= 10; + else if (nd <= DBL_DIG + 1) + z *= 10; + if (nd++ < 9) + y = 10*y + c; + else if (nd <= DBL_DIG + 1) + z = 10*z + c; + nz = 0; + } + } + } + dig_done: + e = 0; + if (c == 'e' || c == 'E') { + if (!nd && !nz && !nz0) { + s = s00; + goto ret; + } + s00 = s; + esign = 0; + switch(c = *++s) { + case '-': + esign = 1; + case '+': + c = *++s; + } + if (c >= '0' && c <= '9') { + while(c == '0') + c = *++s; + if (c > '0' && c <= '9') { + e = c - '0'; + s1 = s; + while((c = *++s) >= '0' && c <= '9') + e = 10*e + c - '0'; + if (s - s1 > 8) + /* Avoid confusion from exponents + * so large that e might overflow. + */ + e = 9999999; + if (esign) + e = -e; + } + else + e = 0; + } + else + s = s00; + } + if (!nd) { + if (!nz && !nz0) + s = s00; + goto ret; + } + e1 = e -= nf; + + /* Now we have nd0 digits, starting at s0, followed by a + * decimal point, followed by nd-nd0 digits. The number we're + * after is the integer represented by those digits times + * 10**e */ + + if (!nd0) + nd0 = nd; + k = nd < DBL_DIG + 1 ? nd : DBL_DIG + 1; + rv = y; + if (k > 9) + rv = tens[k - 9] * rv + z; + if (nd <= DBL_DIG +#ifndef RND_PRODQUOT + && FLT_ROUNDS == 1 +#endif + ) { + if (!e) + goto ret; + if (e > 0) { + if (e <= Ten_pmax) { +#ifdef VAX + goto vax_ovfl_check; +#else + /* rv = */ rounded_product(rv, tens[e]); + goto ret; +#endif + } + i = DBL_DIG - nd; + if (e <= Ten_pmax + i) { + /* A fancier test would sometimes let us do + * this for larger i values. + */ + e -= i; + rv *= tens[i]; +#ifdef VAX + /* VAX exponent range is so narrow we must + * worry about overflow here... + */ + vax_ovfl_check: + addword0(rv, - P*Exp_msk1); + /* rv = */ rounded_product(rv, tens[e]); + if ((word0(rv) & Exp_mask) + > Exp_msk1*(DBL_MAX_EXP+Bias-1-P)) + goto ovfl; + addword0(rv, P*Exp_msk1); +#else + /* rv = */ rounded_product(rv, tens[e]); +#endif + goto ret; + } + } +#ifndef Inaccurate_Divide + else if (e >= -Ten_pmax) { + /* rv = */ rounded_quotient(rv, tens[-e]); + goto ret; + } +#endif + } + e1 += nd - k; + + /* Get starting approximation = rv * 10**e1 */ + + if (e1 > 0) { + if ((i = e1 & 15)) + rv *= tens[i]; + if (e1 &= ~15) { + if (e1 > DBL_MAX_10_EXP) { + ovfl: + errno = ERANGE; +#if defined(sun) && !defined(__svr4__) +/* SunOS defines HUGE_VAL as __infinity(), which is in libm. */ +#undef HUGE_VAL +#endif +#ifndef HUGE_VAL +#define HUGE_VAL 1.7976931348623157E+308 +#endif + rv = HUGE_VAL; + goto ret; + } + if (e1 >>= 4) { + for(j = 0; e1 > 1; j++, e1 >>= 1) + if (e1 & 1) + rv *= bigtens[j]; + /* The last multiplication could overflow. */ + addword0(rv, -P*Exp_msk1); + rv *= bigtens[j]; + if ((z = word0(rv) & Exp_mask) + > Exp_msk1*(DBL_MAX_EXP+Bias-P)) + goto ovfl; + if (z > Exp_msk1*(DBL_MAX_EXP+Bias-1-P)) { + /* set to largest number */ + /* (Can't trust DBL_MAX) */ + setwords(rv, Big0, Big1); + } + else + addword0(rv, P*Exp_msk1); + } + + } + } + else if (e1 < 0) { + e1 = -e1; + if ((i = e1 & 15)) + rv /= tens[i]; + if (e1 &= ~15) { + e1 >>= 4; + for(j = 0; e1 > 1; j++, e1 >>= 1) + if (e1 & 1) + rv *= tinytens[j]; + /* The last multiplication could underflow. */ + rv0 = rv; + rv *= tinytens[j]; + if (!rv) { + rv = 2.*rv0; + rv *= tinytens[j]; + if (!rv) { + undfl: + rv = 0.; + errno = ERANGE; + goto ret; + } + setwords(rv, Tiny0, Tiny1); + /* The refinement below will clean + * this approximation up. + */ + } + } + } + + /* Now the hard part -- adjusting rv to the correct value.*/ + + /* Put digits into bd: true value = bd * 10^e */ + + bd0 = s2b(bd0, s0, nd0, nd, y); + bd = Brealloc(bd, bd0->k); + + for(;;) { + Bcopy(bd, bd0); + bb = d2b(bb, rv, &bbe, &bbbits); /* rv = bb * 2^bbe */ + bs = i2b(bs, 1); + + if (e >= 0) { + bb2 = bb5 = 0; + bd2 = bd5 = e; + } + else { + bb2 = bb5 = -e; + bd2 = bd5 = 0; + } + if (bbe >= 0) + bb2 += bbe; + else + bd2 -= bbe; + bs2 = bb2; +#ifdef Sudden_Underflow +#ifdef IBM + j = 1 + 4*P - 3 - bbbits + ((bbe + bbbits - 1) & 3); +#else + j = P + 1 - bbbits; +#endif +#else + i = bbe + bbbits - 1; /* logb(rv) */ + if (i < Emin) /* denormal */ + j = bbe + (P-Emin); + else + j = P + 1 - bbbits; +#endif + bb2 += j; + bd2 += j; + i = bb2 < bd2 ? bb2 : bd2; + if (i > bs2) + i = bs2; + if (i > 0) { + bb2 -= i; + bd2 -= i; + bs2 -= i; + } + if (bb5 > 0) { + Bigint *b_tmp; + bs = pow5mult(bs, bb5); + b_tmp = mult(b_avail, bs, bb); + b_avail = bb; + bb = b_tmp; + } + if (bb2 > 0) + bb = lshift(bb, bb2); + if (bd5 > 0) + bd = pow5mult(bd, bd5); + if (bd2 > 0) + bd = lshift(bd, bd2); + if (bs2 > 0) + bs = lshift(bs, bs2); + delta = diff(delta, bb, bd); + dsign = delta->sign; + delta->sign = 0; + i = cmp(delta, bs); + if (i < 0) { + /* Error is less than half an ulp -- check for + * special case of mantissa a power of two. + */ + if (dsign || word1(rv) || word0(rv) & Bndry_mask) + break; + delta = lshift(delta,Log2P); + if (cmp(delta, bs) > 0) + goto drop_down; + break; + } + if (i == 0) { + /* exactly half-way between */ + if (dsign) { + if ((word0(rv) & Bndry_mask1) == Bndry_mask1 + && word1(rv) == 0xffffffff) { + /*boundary case -- increment exponent*/ + setword0(rv, (word0(rv) & Exp_mask) + + Exp_msk1); +#ifdef IBM + setword0 (rv, + word0(rv) | (Exp_msk1 >> 4)); +#endif + setword1(rv, 0); + break; + } + } + else if (!(word0(rv) & Bndry_mask) && !word1(rv)) { + drop_down: + /* boundary case -- decrement exponent */ +#ifdef Sudden_Underflow + L = word0(rv) & Exp_mask; +#ifdef IBM + if (L < Exp_msk1) +#else + if (L <= Exp_msk1) +#endif + goto undfl; + L -= Exp_msk1; +#else + L = (word0(rv) & Exp_mask) - Exp_msk1; +#endif + setwords(rv, L | Bndry_mask1, 0xffffffff); +#ifdef IBM + continue; +#else + break; +#endif + } +#ifndef ROUND_BIASED + if (!(word1(rv) & LSB)) + break; +#endif + if (dsign) + rv += ulp(rv); +#ifndef ROUND_BIASED + else { + rv -= ulp(rv); +#ifndef Sudden_Underflow + if (!rv) + goto undfl; +#endif + } +#endif + break; + } + if ((aadj = ratio(delta, bs)) <= 2.) { + if (dsign) + aadj = aadj1 = 1.; + else if (word1(rv) || word0(rv) & Bndry_mask) { +#ifndef Sudden_Underflow + if (word1(rv) == Tiny1 && !word0(rv)) + goto undfl; +#endif + aadj = 1.; + aadj1 = -1.; + } + else { + /* special case -- power of FLT_RADIX to be */ + /* rounded down... */ + + if (aadj < 2./FLT_RADIX) + aadj = 1./FLT_RADIX; + else + aadj *= 0.5; + aadj1 = -aadj; + } + } + else { + aadj *= 0.5; + aadj1 = dsign ? aadj : -aadj; +#ifdef Check_FLT_ROUNDS + switch(FLT_ROUNDS) { + case 2: /* towards +infinity */ + aadj1 -= 0.5; + break; + case 0: /* towards 0 */ + case 3: /* towards -infinity */ + aadj1 += 0.5; + } +#else + if (FLT_ROUNDS == 0) + aadj1 += 0.5; +#endif + } + y = word0(rv) & Exp_mask; + + /* Check for overflow */ + + if (y == Exp_msk1*(DBL_MAX_EXP+Bias-1)) { + rv0 = rv; + addword0(rv, - P*Exp_msk1); + adj = aadj1 * ulp(rv); + rv += adj; + if ((word0(rv) & Exp_mask) >= + Exp_msk1*(DBL_MAX_EXP+Bias-P)) { + if (word0(rv0) == Big0 && word1(rv0) == Big1) + goto ovfl; + setwords(rv, Big0, Big1); + continue; + } + else + addword0(rv, P*Exp_msk1); + } + else { +#ifdef Sudden_Underflow + if ((word0(rv) & Exp_mask) <= P*Exp_msk1) { + rv0 = rv; + addword0(rv, P*Exp_msk1); + adj = aadj1 * ulp(rv); + rv += adj; +#ifdef IBM + if ((word0(rv) & Exp_mask) < P*Exp_msk1) +#else + if ((word0(rv) & Exp_mask) <= P*Exp_msk1) +#endif + { + if (word0(rv0) == Tiny0 + && word1(rv0) == Tiny1) + goto undfl; + setwords(rv, Tiny0, Tiny1); + continue; + } + else + addword0(rv, -P*Exp_msk1); + } + else { + adj = aadj1 * ulp(rv); + rv += adj; + } +#else + /* Compute adj so that the IEEE rounding rules will + * correctly round rv + adj in some half-way cases. + * If rv * ulp(rv) is denormalized (i.e., + * y <= (P-1)*Exp_msk1), we must adjust aadj to avoid + * trouble from bits lost to denormalization; + * example: 1.2e-307 . + */ + if (y <= (P-1)*Exp_msk1 && aadj >= 1.) { + aadj1 = (double)(int)(aadj + 0.5); + if (!dsign) + aadj1 = -aadj1; + } + adj = aadj1 * ulp(rv); + rv += adj; +#endif + } + z = word0(rv) & Exp_mask; + if (y == z) { + /* Can we stop now? */ + L = (_G_int32_t)aadj; + aadj -= L; + /* The tolerances below are conservative. */ + if (dsign || word1(rv) || word0(rv) & Bndry_mask) { + if (aadj < .4999999 || aadj > .5000001) + break; + } + else if (aadj < .4999999/FLT_RADIX) + break; + } + } + Bfree(bb); + Bfree(bd); + Bfree(bs); + Bfree(bd0); + Bfree(delta); + Bfree(b_avail); + ret: + if (se) + *se = (char *)s; + return sign ? -rv : rv; + } + +static int +quorem +#ifdef KR_headers + (b, S) Bigint *b, *S; +#else + (Bigint *b, Bigint *S) +#endif +{ + int n; + _G_int32_t borrow, y; + unsigned32 carry, q, ys; + unsigned32 *bx, *bxe, *sx, *sxe; + _G_int32_t z; + unsigned32 si, zs; + + n = S->wds; +#ifdef DEBUG + /*debug*/ if (b->wds > n) + /*debug*/ Bug("oversize b in quorem"); +#endif + if (b->wds < n) + return 0; + sx = S->x; + sxe = sx + --n; + bx = b->x; + bxe = bx + n; + q = *bxe / (*sxe + 1); /* ensure q <= true quotient */ +#ifdef DEBUG + /*debug*/ if (q > 9) + /*debug*/ Bug("oversized quotient in quorem"); +#endif + if (q) { + borrow = 0; + carry = 0; + do { + si = *sx++; + ys = (si & 0xffff) * q + carry; + zs = (si >> 16) * q + (ys >> 16); + carry = zs >> 16; + y = (*bx & 0xffff) - (ys & 0xffff) + borrow; + borrow = y >> 16; + Sign_Extend(borrow, y); + z = (*bx >> 16) - (zs & 0xffff) + borrow; + borrow = z >> 16; + Sign_Extend(borrow, z); + Storeinc(bx, z, y); + } + while(sx <= sxe); + if (!*bxe) { + bx = b->x; + while(--bxe > bx && !*bxe) + --n; + b->wds = n; + } + } + if (cmp(b, S) >= 0) { + q++; + borrow = 0; + carry = 0; + bx = b->x; + sx = S->x; + do { + si = *sx++; + ys = (si & 0xffff) + carry; + zs = (si >> 16) + (ys >> 16); + carry = zs >> 16; + y = (*bx & 0xffff) - (ys & 0xffff) + borrow; + borrow = y >> 16; + Sign_Extend(borrow, y); + z = (*bx >> 16) - (zs & 0xffff) + borrow; + borrow = z >> 16; + Sign_Extend(borrow, z); + Storeinc(bx, z, y); + } + while(sx <= sxe); + bx = b->x; + bxe = bx + n; + if (!*bxe) { + while(--bxe > bx && !*bxe) + --n; + b->wds = n; + } + } + return q; + } + +/* dtoa for IEEE arithmetic (dmg): convert double to ASCII string. + * + * Inspired by "How to Print Floating-Point Numbers Accurately" by + * Guy L. Steele, Jr. and Jon L. White [Proc. ACM SIGPLAN '90, pp. 92-101]. + * + * Modifications: + * 1. Rather than iterating, we use a simple numeric overestimate + * to determine k = floor(log10(d)). We scale relevant + * quantities using O(log2(k)) rather than O(k) multiplications. + * 2. For some modes > 2 (corresponding to ecvt and fcvt), we don't + * try to generate digits strictly left to right. Instead, we + * compute with fewer bits and propagate the carry if necessary + * when rounding the final digit up. This is often faster. + * 3. Under the assumption that input will be rounded nearest, + * mode 0 renders 1e23 as 1e23 rather than 9.999999999999999e22. + * That is, we allow equality in stopping tests when the + * round-nearest rule will give the same floating-point value + * as would satisfaction of the stopping test with strict + * inequality. + * 4. We remove common factors of powers of 2 from relevant + * quantities. + * 5. When converting floating-point integers less than 1e16, + * we use floating-point arithmetic rather than resorting + * to multiple-precision integers. + * 6. When asked to produce fewer than 15 digits, we first try + * to get by with floating-point arithmetic; we resort to + * multiple-precision integer arithmetic only if we cannot + * guarantee that the floating-point calculation has given + * the correctly rounded result. For k requested digits and + * "uniformly" distributed input, the probability is + * something like 10^(k-15) that we must resort to the long + * calculation. + */ + + char * +_IO_dtoa +#ifdef KR_headers + (d, mode, ndigits, decpt, sign, rve) + double d; int mode, ndigits, *decpt, *sign; char **rve; +#else + (double d, int mode, int ndigits, int *decpt, int *sign, char **rve) +#endif +{ + /* Arguments ndigits, decpt, sign are similar to those + of ecvt and fcvt; trailing zeros are suppressed from + the returned string. If not null, *rve is set to point + to the end of the return value. If d is +-Infinity or NaN, + then *decpt is set to 9999. + + mode: + 0 ==> shortest string that yields d when read in + and rounded to nearest. + 1 ==> like 0, but with Steele & White stopping rule; + e.g. with IEEE P754 arithmetic , mode 0 gives + 1e23 whereas mode 1 gives 9.999999999999999e22. + 2 ==> max(1,ndigits) significant digits. This gives a + return value similar to that of ecvt, except + that trailing zeros are suppressed. + 3 ==> through ndigits past the decimal point. This + gives a return value similar to that from fcvt, + except that trailing zeros are suppressed, and + ndigits can be negative. + 4-9 should give the same return values as 2-3, i.e., + 4 <= mode <= 9 ==> same return as mode + 2 + (mode & 1). These modes are mainly for + debugging; often they run slower but sometimes + faster than modes 2-3. + 4,5,8,9 ==> left-to-right digit generation. + 6-9 ==> don't try fast floating-point estimate + (if applicable). + + Values of mode other than 0-9 are treated as mode 0. + + Sufficient space is allocated to the return value + to hold the suppressed trailing zeros. + */ + + int bbits, b2, b5, be, dig, i, ieps, ilim, ilim0, ilim1, + j, j1, k, k0, k_check, leftright, m2, m5, s2, s5, + spec_case, try_quick; + _G_int32_t L; +#ifndef Sudden_Underflow + int denorm; +#endif + Bigint _b_avail, _b, _mhi, _mlo, _S; + Bigint *b_avail = Binit(&_b_avail); + Bigint *b = Binit(&_b); + Bigint *S = Binit(&_S); + /* mhi and mlo are only set and used if leftright. */ + Bigint *mhi = NULL, *mlo = NULL; + double d2, ds, eps; + char *s, *s0; + static Bigint *result = NULL; + static int result_k; + + TEST_ENDIANNESS; + if (result) { + /* result is contains a string, so its fields (interpreted + as a Bigint have been trashed. Restore them. + This is a really ugly interface - result should + not be static, since that is not thread-safe. FIXME. */ + result->k = result_k; + result->maxwds = 1 << result_k; + result->on_stack = 0; + } + + if (word0(d) & Sign_bit) { + /* set sign for everything, including 0's and NaNs */ + *sign = 1; + setword0(d, word0(d) & ~Sign_bit); /* clear sign bit */ + } + else + *sign = 0; + +#if defined(IEEE_Arith) + defined(VAX) +#ifdef IEEE_Arith + if ((word0(d) & Exp_mask) == Exp_mask) +#else + if (word0(d) == 0x8000) +#endif + { + /* Infinity or NaN */ + *decpt = 9999; +#ifdef IEEE_Arith + if (!word1(d) && !(word0(d) & 0xfffff)) + { + s = "Infinity"; + if (rve) + *rve = s + 8; + } + else +#endif + { + s = "NaN"; + if (rve) + *rve = s +3; + } + return s; + } +#endif +#ifdef IBM + d += 0; /* normalize */ +#endif + if (!d) { + *decpt = 1; + s = "0"; + if (rve) + *rve = s + 1; + return s; + } + + b = d2b(b, d, &be, &bbits); + i = (int)(word0(d) >> Exp_shift1 & (Exp_mask>>Exp_shift1)); +#ifndef Sudden_Underflow + if (i) { +#endif + d2 = d; + setword0(d2, (word0(d2) & Frac_mask1) | Exp_11); +#ifdef IBM + if (j = 11 - hi0bits(word0(d2) & Frac_mask)) + d2 /= 1 << j; +#endif + + i -= Bias; +#ifdef IBM + i <<= 2; + i += j; +#endif +#ifndef Sudden_Underflow + denorm = 0; + } + else { + /* d is denormalized */ + unsigned32 x; + + i = bbits + be + (Bias + (P-1) - 1); + x = i > 32 ? word0(d) << (64 - i) | word1(d) >> (i - 32) + : word1(d) << (32 - i); + d2 = x; + addword0(d2, - 31*Exp_msk1); /* adjust exponent */ + i -= (Bias + (P-1) - 1) + 1; + denorm = 1; + } +#endif + + /* Now i is the unbiased base-2 exponent. */ + + /* log(x) ~=~ log(1.5) + (x-1.5)/1.5 + * log10(x) = log(x) / log(10) + * ~=~ log(1.5)/log(10) + (x-1.5)/(1.5*log(10)) + * log10(d) = i*log(2)/log(10) + log10(d2) + * + * This suggests computing an approximation k to log10(d) by + * + * k = i*0.301029995663981 + * + ( (d2-1.5)*0.289529654602168 + 0.176091259055681 ); + * + * We want k to be too large rather than too small. + * The error in the first-order Taylor series approximation + * is in our favor, so we just round up the constant enough + * to compensate for any error in the multiplication of + * (i) by 0.301029995663981; since |i| <= 1077, + * and 1077 * 0.30103 * 2^-52 ~=~ 7.2e-14, + * adding 1e-13 to the constant term more than suffices. + * Hence we adjust the constant term to 0.1760912590558. + * (We could get a more accurate k by invoking log10, + * but this is probably not worthwhile.) + */ + + ds = (d2-1.5)*0.289529654602168 + 0.1760912590558 + i*0.301029995663981; + k = (int)ds; + if (ds < 0. && ds != k) + k--; /* want k = floor(ds) */ + k_check = 1; + if (k >= 0 && k <= Ten_pmax) { + if (d < tens[k]) + k--; + k_check = 0; + } + j = bbits - i - 1; + if (j >= 0) { + b2 = 0; + s2 = j; + } + else { + b2 = -j; + s2 = 0; + } + if (k >= 0) { + b5 = 0; + s5 = k; + s2 += k; + } + else { + b2 -= k; + b5 = -k; + s5 = 0; + } + if (mode < 0 || mode > 9) + mode = 0; + try_quick = 1; + if (mode > 5) { + mode -= 4; + try_quick = 0; + } + leftright = 1; + switch(mode) { + case 0: + case 1: + ilim = ilim1 = -1; + i = 18; + ndigits = 0; + break; + case 2: + leftright = 0; + /* no break */ + case 4: + if (ndigits <= 0) + ndigits = 1; + ilim = ilim1 = i = ndigits; + break; + case 3: + leftright = 0; + /* no break */ + case 5: + i = ndigits + k + 1; + ilim = i; + ilim1 = i - 1; + if (i <= 0) + i = 1; + } + /* i is now an upper bound of the number of digits to generate. */ + j = sizeof(unsigned32) * (1<<BIGINT_MINIMUM_K); + /* The test is <= so as to allow room for the final '\0'. */ + for(result_k = BIGINT_MINIMUM_K; BIGINT_HEADER_SIZE + j <= i; + j <<= 1) result_k++; + if (!result || result_k > result->k) + { + Bfree (result); + result = Balloc(result_k); + } + s = s0 = (char *)result; + + if (ilim >= 0 && ilim <= Quick_max && try_quick) { + + /* Try to get by with floating-point arithmetic. */ + + i = 0; + d2 = d; + k0 = k; + ilim0 = ilim; + ieps = 2; /* conservative */ + if (k > 0) { + ds = tens[k&0xf]; + j = k >> 4; + if (j & Bletch) { + /* prevent overflows */ + j &= Bletch - 1; + d /= bigtens[n_bigtens-1]; + ieps++; + } + for(; j; j >>= 1, i++) + if (j & 1) { + ieps++; + ds *= bigtens[i]; + } + d /= ds; + } + else if ((j1 = -k)) { + d *= tens[j1 & 0xf]; + for(j = j1 >> 4; j; j >>= 1, i++) + if (j & 1) { + ieps++; + d *= bigtens[i]; + } + } + if (k_check && d < 1. && ilim > 0) { + if (ilim1 <= 0) + goto fast_failed; + ilim = ilim1; + k--; + d *= 10.; + ieps++; + } + eps = ieps*d + 7.; + addword0(eps, - (P-1)*Exp_msk1); + if (ilim == 0) { + d -= 5.; + if (d > eps) + goto one_digit; + if (d < -eps) + goto no_digits; + goto fast_failed; + } +#ifndef No_leftright + if (leftright) { + /* Use Steele & White method of only + * generating digits needed. + */ + eps = 0.5/tens[ilim-1] - eps; + for(i = 0;;) { + L = (_G_int32_t)d; + d -= L; + *s++ = '0' + (int)L; + if (d < eps) + goto ret1; + if (1. - d < eps) + goto bump_up; + if (++i >= ilim) + break; + eps *= 10.; + d *= 10.; + } + } + else { +#endif + /* Generate ilim digits, then fix them up. */ + eps *= tens[ilim-1]; + for(i = 1;; i++, d *= 10.) { + L = (_G_int32_t)d; + d -= L; + *s++ = '0' + (int)L; + if (i == ilim) { + if (d > 0.5 + eps) + goto bump_up; + else if (d < 0.5 - eps) { + while(*--s == '0'); + s++; + goto ret1; + } + break; + } + } +#ifndef No_leftright + } +#endif + fast_failed: + s = s0; + d = d2; + k = k0; + ilim = ilim0; + } + + /* Do we have a "small" integer? */ + + if (be >= 0 && k <= Int_max) { + /* Yes. */ + ds = tens[k]; + if (ndigits < 0 && ilim <= 0) { + if (ilim < 0 || d <= 5*ds) + goto no_digits; + goto one_digit; + } + for(i = 1;; i++) { + L = (_G_int32_t)(d / ds); + d -= L*ds; +#ifdef Check_FLT_ROUNDS + /* If FLT_ROUNDS == 2, L will usually be high by 1 */ + if (d < 0) { + L--; + d += ds; + } +#endif + *s++ = '0' + (int)L; + if (i == ilim) { + d += d; + if (d > ds || (d == ds && L & 1)) { + bump_up: + while(*--s == '9') + if (s == s0) { + k++; + *s = '0'; + break; + } + ++*s++; + } + break; + } + if (!(d *= 10.)) + break; + } + goto ret1; + } + + m2 = b2; + m5 = b5; + if (leftright) { + if (mode < 2) { + i = +#ifndef Sudden_Underflow + denorm ? be + (Bias + (P-1) - 1 + 1) : +#endif +#ifdef IBM + 1 + 4*P - 3 - bbits + ((bbits + be - 1) & 3); +#else + 1 + P - bbits; +#endif + } + else { + j = ilim - 1; + if (m5 >= j) + m5 -= j; + else { + s5 += j -= m5; + b5 += j; + m5 = 0; + } + if ((i = ilim) < 0) { + m2 -= i; + i = 0; + } + } + b2 += i; + s2 += i; + mhi = i2b(Binit(&_mhi), 1); + } + if (m2 > 0 && s2 > 0) { + i = m2 < s2 ? m2 : s2; + b2 -= i; + m2 -= i; + s2 -= i; + } + if (b5 > 0) { + if (leftright) { + if (m5 > 0) { + Bigint *b_tmp; + mhi = pow5mult(mhi, m5); + b_tmp = mult(b_avail, mhi, b); + b_avail = b; + b = b_tmp; + } + if ((j = b5 - m5)) + b = pow5mult(b, j); + } + else + b = pow5mult(b, b5); + } + S = i2b(S, 1); + if (s5 > 0) + S = pow5mult(S, s5); + + /* Check for special case that d is a normalized power of 2. */ + + if (mode < 2) { + if (!word1(d) && !(word0(d) & Bndry_mask) +#ifndef Sudden_Underflow + && word0(d) & Exp_mask +#endif + ) { + /* The special case */ + b2 += Log2P; + s2 += Log2P; + spec_case = 1; + } + else + spec_case = 0; + } + + /* Arrange for convenient computation of quotients: + * shift left if necessary so divisor has 4 leading 0 bits. + * + * Perhaps we should just compute leading 28 bits of S once + * and for all and pass them and a shift to quorem, so it + * can do shifts and ors to compute the numerator for q. + */ + if ((i = ((s5 ? 32 - hi0bits(S->x[S->wds-1]) : 1) + s2) & 0x1f)) + i = 32 - i; + if (i > 4) { + i -= 4; + b2 += i; + m2 += i; + s2 += i; + } + else if (i < 4) { + i += 28; + b2 += i; + m2 += i; + s2 += i; + } + if (b2 > 0) + b = lshift(b, b2); + if (s2 > 0) + S = lshift(S, s2); + if (k_check) { + if (cmp(b,S) < 0) { + k--; + b = multadd(b, 10, 0); /* we botched the k estimate */ + if (leftright) + mhi = multadd(mhi, 10, 0); + ilim = ilim1; + } + } + if (ilim <= 0 && mode > 2) { + if (ilim < 0 || cmp(b,S = multadd(S,5,0)) <= 0) { + /* no digits, fcvt style */ + no_digits: + k = -1 - ndigits; + goto ret; + } + one_digit: + *s++ = '1'; + k++; + goto ret; + } + if (leftright) { + if (m2 > 0) + mhi = lshift(mhi, m2); + + /* Compute mlo -- check for special case + * that d is a normalized power of 2. + */ + + if (spec_case) { + mlo = Brealloc(Binit(&_mlo), mhi->k); + Bcopy(mlo, mhi); + mhi = lshift(mhi, Log2P); + } + else + mlo = mhi; + + for(i = 1;;i++) { + dig = quorem(b,S) + '0'; + /* Do we yet have the shortest decimal string + * that will round to d? + */ + j = cmp(b, mlo); + b_avail = diff(b_avail, S, mhi); /* b_avail = S - mi */ + j1 = b_avail->sign ? 1 : cmp(b, b_avail); +#ifndef ROUND_BIASED + if (j1 == 0 && !mode && !(word1(d) & 1)) { + if (dig == '9') + goto round_9_up; + if (j > 0) + dig++; + *s++ = dig; + goto ret; + } +#endif + if (j < 0 || (j == 0 && !mode +#ifndef ROUND_BIASED + && !(word1(d) & 1) +#endif + )) { + if (j1 > 0) { + b = lshift(b, 1); + j1 = cmp(b, S); + if ((j1 > 0 || (j1 == 0 && dig & 1)) + && dig++ == '9') + goto round_9_up; + } + *s++ = dig; + goto ret; + } + if (j1 > 0) { + if (dig == '9') { /* possible if i == 1 */ + round_9_up: + *s++ = '9'; + goto roundoff; + } + *s++ = dig + 1; + goto ret; + } + *s++ = dig; + if (i == ilim) + break; + b = multadd(b, 10, 0); + if (mlo == mhi) + mlo = mhi = multadd(mhi, 10, 0); + else { + mlo = multadd(mlo, 10, 0); + mhi = multadd(mhi, 10, 0); + } + } + } + else + for(i = 1;; i++) { + *s++ = dig = quorem(b,S) + '0'; + if (i >= ilim) + break; + b = multadd(b, 10, 0); + } + + /* Round off last digit */ + + b = lshift(b, 1); + j = cmp(b, S); + if (j > 0 || (j == 0 && dig & 1)) { + roundoff: + while(*--s == '9') + if (s == s0) { + k++; + *s++ = '1'; + goto ret; + } + ++*s++; + } + else { + while(*--s == '0'); + s++; + } + ret: + Bfree(b_avail); + Bfree(S); + if (mhi) { + if (mlo && mlo != mhi) + Bfree(mlo); + Bfree(mhi); + } + ret1: + Bfree(b); + *s = 0; + *decpt = k + 1; + if (rve) + *rve = s; + return s0; + } +#endif /* _IO_USE_DTOA */ diff --git a/gnu/lib/libg++/libio/floatio.h b/gnu/lib/libg++/libio/floatio.h new file mode 100644 index 00000000000..827767bde35 --- /dev/null +++ b/gnu/lib/libg++/libio/floatio.h @@ -0,0 +1,51 @@ +/* +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. + * + * %W% (Berkeley) %G% + */ + +/* + * Floating point scanf/printf (input/output) definitions. + */ + +/* 11-bit exponent (VAX G floating point) is 308 decimal digits */ +#define MAXEXP 308 +/* 128 bit fraction takes up 39 decimal digits; max reasonable precision */ +#define MAXFRACT 39 diff --git a/gnu/lib/libg++/libio/fstream.cc b/gnu/lib/libg++/libio/fstream.cc new file mode 100644 index 00000000000..8930e0b9271 --- /dev/null +++ b/gnu/lib/libg++/libio/fstream.cc @@ -0,0 +1,110 @@ +/* This is part of libio/iostream, providing -*- C++ -*- input/output. +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. + +Written by Per Bothner (bothner@cygnus.com). */ + +#ifdef __GNUG__ +#pragma implementation +#endif +#define _STREAM_COMPAT +extern "C" { +#include "libioP.h" +} +#include <fstream.h> + +inline void +fstreambase::__fb_init() +{ +#ifdef _IO_NEW_STREAMS +#if !_IO_UNIFIED_JUMPTABLES + /* Uses the _IO_file_jump jumptable, for eficiency. */ + __my_fb._jumps = &_IO_file_jumps; + __my_fb._vtable() = builtinbuf_vtable; +#endif + init (&__my_fb); +#else + init(filebuf::__new()); + _flags &= ~ios::dont_close; +#endif +} + +fstreambase::fstreambase() +{ + __fb_init (); +} + +fstreambase::fstreambase(int fd) +{ + __fb_init (); + _IO_file_attach(rdbuf(), fd); +} + +fstreambase::fstreambase(const char *name, int mode, int prot) +{ + __fb_init (); + if (!rdbuf()->open(name, mode, prot)) + set(ios::badbit); +} + +fstreambase::fstreambase(int fd, char *p, int l) +{ +#ifdef _IO_NEW_STREAMS + __fb_init (); +#else + init(filebuf::__new()); +#endif + _IO_file_attach(rdbuf(), fd); + _IO_file_setbuf(rdbuf(), p, l); +} + +void fstreambase::open(const char *name, int mode, int prot) +{ + clear(); + if (!rdbuf()->open(name, mode, prot)) + set(ios::badbit); +} + +void fstreambase::close() +{ + if (!rdbuf()->close()) + set(ios::failbit); +} + +void fstreambase::attach(int fd) +{ + if (!rdbuf()->attach(fd)) + set(ios::failbit); +} + +#if 0 +static int mode_to_sys(enum open_mode mode) +{ + return O_WRONLY; +} + +static char* fopen_cmd_arg(io_mode i) +{ + return "w"; +} +#endif diff --git a/gnu/lib/libg++/libio/fstream.h b/gnu/lib/libg++/libio/fstream.h new file mode 100644 index 00000000000..398cd31d75a --- /dev/null +++ b/gnu/lib/libg++/libio/fstream.h @@ -0,0 +1,92 @@ +/* This is part of libio/iostream, providing -*- C++ -*- input/output. +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. */ + +#ifndef _FSTREAM_H +#define _FSTREAM_H +#ifdef __GNUG__ +#pragma interface +#endif +#include <iostream.h> + +extern "C++" { +class fstreambase : virtual public ios { +#ifdef _IO_NEW_STREAMS + filebuf __my_fb; +#endif + void __fb_init (); + public: + fstreambase(); + fstreambase(int fd); + fstreambase(int fd, char *p, int l); /* Deprecated */ + fstreambase(const char *name, int mode, int prot=0664); + void close(); +#ifdef _IO_NEW_STREAMS + filebuf* rdbuf() const { return (filebuf*)&__my_fb; } +#else + filebuf* rdbuf() const { return (filebuf*) ios::rdbuf(); } +#endif + void open(const char *name, int mode, int prot=0664); + int is_open() const { return rdbuf()->is_open(); } + void setbuf(char *ptr, int len) { rdbuf()->setbuf(ptr, len); } + void attach(int fd); +#ifdef _STREAM_COMPAT + int filedesc() { return rdbuf()->fd(); } + fstreambase& raw() { rdbuf()->setbuf(NULL, 0); return *this; } +#endif +}; + +class ifstream : public fstreambase, public istream { + public: + ifstream() : fstreambase() { } + ifstream(int fd) : fstreambase(fd) { } + ifstream(int fd, char *p, int l) : fstreambase(fd, p, l) { } /*Deprecated*/ + ifstream(const char *name, int mode=ios::in, int prot=0664) + : fstreambase(name, mode, prot) { } + void open(const char *name, int mode=ios::in, int prot=0664) + { fstreambase::open(name, mode, prot); } +}; + +class ofstream : public fstreambase, public ostream { + public: + ofstream() : fstreambase() { } + ofstream(int fd) : fstreambase(fd) { } + ofstream(int fd, char *p, int l) : fstreambase(fd, p, l) { } /*Deprecated*/ + ofstream(const char *name, int mode=ios::out, int prot=0664) + : fstreambase(name, mode, prot) { } + void open(const char *name, int mode=ios::out, int prot=0664) + { fstreambase::open(name, mode, prot); } +}; + +class fstream : public fstreambase, public iostream { + public: + fstream() : fstreambase() { } + fstream(int fd) : fstreambase(fd) { } + fstream(const char *name, int mode, int prot=0664) + : fstreambase(name, mode, prot) { } + fstream(int fd, char *p, int l) : fstreambase(fd, p, l) { } /*Deprecated*/ + void open(const char *name, int mode, int prot=0664) + { fstreambase::open(name, mode, prot); } +}; +} // extern "C++" +#endif /*!_FSTREAM_H*/ diff --git a/gnu/lib/libg++/libio/genops.c b/gnu/lib/libg++/libio/genops.c new file mode 100644 index 00000000000..7eb2d43ee19 --- /dev/null +++ b/gnu/lib/libg++/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/gnu/lib/libg++/libio/indstream.cc b/gnu/lib/libg++/libio/indstream.cc new file mode 100644 index 00000000000..e74f4dbac4f --- /dev/null +++ b/gnu/lib/libg++/libio/indstream.cc @@ -0,0 +1,116 @@ +/* This is part of libio/iostream, providing -*- C++ -*- input/output. +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. + +Written by Per Bothner (bothner@cygnus.com). */ + +#ifdef __GNUG__ +#pragma implementation +#endif + +#include <indstream.h> + +indirectbuf::indirectbuf(streambuf *get, streambuf *put, int delete_mode) +: streambuf() +{ + _get_stream = get; + _put_stream = put == NULL ? get : put; + _delete_flags = delete_mode; +} + +indirectbuf::~indirectbuf() +{ + if (_delete_flags & ios::in) delete get_stream(); + if (_delete_flags & ios::out) delete put_stream(); +} + +streamsize indirectbuf::xsputn(const char* s, streamsize n) +{ + return put_stream()->sputn(s, n); +} + +streamsize indirectbuf::xsgetn(char* s, streamsize n) +{ + return get_stream()->sgetn(s, n); +} + +int indirectbuf::overflow(int c /* = EOF */) +{ + if (c == EOF) + return put_stream()->overflow(c); + else + return put_stream()->sputc(c); +} + +int indirectbuf::underflow() +{ + return get_stream()->sbumpc(); +} + +streampos indirectbuf::seekoff(streamoff off, _seek_dir dir, int mode) +{ + int ret_val = 0; + int select = mode == 0 ? (ios::in|ios::out) : mode; + streambuf *gbuf = (select & ios::in) ? get_stream() : (streambuf*)NULL; + streambuf *pbuf = (select & ios::out) ? put_stream() : (streambuf*)NULL; + if (gbuf == pbuf) + ret_val = gbuf->seekoff(off, dir, mode); + else { + if (gbuf) + ret_val = gbuf->seekoff(off, dir, ios::in); + if (pbuf && ret_val != EOF) + ret_val = pbuf->seekoff(off, dir, ios::out); + } + return ret_val; +} + +streampos indirectbuf::seekpos(streampos pos, int mode) +{ + int ret_val = EOF; + int select = mode == 0 ? (ios::in|ios::out) : mode; + streambuf *gbuf = (select & ios::in) ? get_stream() : (streambuf*)NULL; + streambuf *pbuf = (select & ios::out) ? put_stream() : (streambuf*)NULL; + if (gbuf == pbuf) + ret_val = gbuf->seekpos(pos, mode); + else { + if (gbuf) + ret_val = gbuf->seekpos(pos, ios::in); + if (pbuf && ret_val != EOF) + ret_val = pbuf->seekpos(pos, ios::out); + } + return ret_val; +} + +int indirectbuf::sync() +{ + streambuf *gbuf = get_stream(); + int get_ret_val = gbuf ? gbuf->sync() : 0; + streambuf *pbuf = put_stream(); + int put_ret_val = (pbuf && pbuf != gbuf) ? pbuf->sync() : 0; + return get_ret_val || put_ret_val; +} + +int indirectbuf::pbackfail(int c) +{ + return get_stream()->sputbackc(c); +} diff --git a/gnu/lib/libg++/libio/indstream.h b/gnu/lib/libg++/libio/indstream.h new file mode 100644 index 00000000000..6afffdd9bc9 --- /dev/null +++ b/gnu/lib/libg++/libio/indstream.h @@ -0,0 +1,76 @@ +/* This is part of libio/iostream, providing -*- C++ -*- input/output. +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. + +Written by Per Bothner (bothner@cygnus.com). */ + +#ifndef _INDSTREAM_H +#define _INDSTREAM_H + +#ifdef __GNUG__ +#pragma interface +#endif + +#include <iostream.h> + +extern "C++" { +// An indirectbuf is one that forwards all of its I/O requests +// to another streambuf. +// All get-related requests are sent to get_stream(). +// All put-related requests are sent to put_stream(). + +// An indirectbuf can be used to implement Common Lisp +// synonym-streams and two-way-streams. +// +// class synonymbuf : public indirectbuf { +// Symbol *sym; +// synonymbuf(Symbol *s) { sym = s; } +// virtual streambuf *lookup_stream(int mode) { +// return coerce_to_streambuf(lookup_value(sym)); } +// }; + +class indirectbuf : public streambuf { + protected: + streambuf *_get_stream; // Optional cache for get_stream(). + streambuf *_put_stream; // Optional cache for put_stream(). + int _delete_flags; + public: + streambuf *get_stream() + { return _get_stream ? _get_stream : lookup_stream(ios::in); } + streambuf *put_stream() + { return _put_stream ? _put_stream : lookup_stream(ios::out); } + virtual streambuf *lookup_stream(int/*mode*/) { return NULL; } // ERROR! + indirectbuf(streambuf *get=NULL, streambuf *put=NULL, int delete_mode=0); + virtual ~indirectbuf(); + virtual streamsize xsputn(const char* s, streamsize n); + virtual streamsize xsgetn(char* s, streamsize n); + virtual int underflow(); + virtual int overflow(int c = EOF); + virtual streampos seekoff(streamoff, _seek_dir, int mode=ios::in|ios::out); + virtual streampos seekpos(streampos pos, int mode = ios::in|ios::out); + virtual int sync(); + virtual int pbackfail(int c); +}; +} // extern "C++" + +#endif /* !_INDSTREAM_H */ diff --git a/gnu/lib/libg++/libio/ioassign.cc b/gnu/lib/libg++/libio/ioassign.cc new file mode 100644 index 00000000000..5b8e68bbf53 --- /dev/null +++ b/gnu/lib/libg++/libio/ioassign.cc @@ -0,0 +1,49 @@ +/* This is part of libio/iostream, providing -*- C++ -*- input/output. +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. */ + +/* Written by Per Bothner (bothner@cygnus.com). */ + +#include <iostream.h> +#include "libioP.h" + +// These method are provided for backward compatibility reasons. +// It's generally poor style to use them. +// They are not supported by the ANSI/ISO working paper. + +_IO_istream_withassign& _IO_istream_withassign::operator=(istream& rhs) +{ + if (&rhs != (istream*)this) + { + init (rhs.rdbuf ()); + _gcount = 0; + } + return *this; +} + +_IO_ostream_withassign& _IO_ostream_withassign::operator=(ostream& rhs) +{ + if (&rhs != (ostream*)this) + init (rhs.rdbuf ()); + return *this; +} diff --git a/gnu/lib/libg++/libio/ioextend.cc b/gnu/lib/libg++/libio/ioextend.cc new file mode 100644 index 00000000000..e0ec0cb6499 --- /dev/null +++ b/gnu/lib/libg++/libio/ioextend.cc @@ -0,0 +1,132 @@ +/* +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 <iostream.h> + +static int __xalloc = 0; + +int ios::xalloc() +{ + return __xalloc++; +} + +static ios::fmtflags __used_fmt_flags += ios::skipws | ios::left | ios::right | ios::internal +| ios::dec | ios::oct | ios::hex | ios::showbase | ios::showpoint +| ios::uppercase | ios::showpos | ios::scientific | ios::fixed +#ifndef _IO_NEW_STREAMS +| ios::dont_close +#endif +| ios::unitbuf | ios::stdio; + +ios::fmtflags ios::bitalloc() +{ + fmtflags bit_to_try = (fmtflags)1; + for (; bit_to_try; bit_to_try <<= 1) + { + if ((__used_fmt_flags & bit_to_try) == 0) + { + __used_fmt_flags |= bit_to_try; + return bit_to_try; + } + } + return 0; +} + +// NOTE: This implementation of ios::iword and ios::pword assumes +// that these methods are seldom used, so we want to minimize +// the space and time overhead when NOT using these methods. +// +// ANSI specifies two conceptually-infinite arrays, one whose +// elements are longs, and one whose elements are (void*)s. +// We implement this as a single array, each of whose element is +// a (struct ptr_and_long), which has space for both a long and a void*. +// We also specify that (the i field of) the 0'th element of the array +// contains the allocated length of the array (not counting that +// initial element). + +struct ptr_and_long { + void *p; + long i; +}; + +static struct ptr_and_long& +get_array_element(ios& io, int index) +{ + if (index < 0) + io._throw_failure(); + register struct ptr_and_long *array = (ptr_and_long*)io._arrays; + int old_length = array == NULL ? 0 : array[0].i; + if (index >= old_length) + { + register int i; + int new_length = index + 10; + register struct ptr_and_long *new_array + = new ptr_and_long[1 + new_length]; + if (array != NULL) + { + for (i = 1; i <= old_length; i++) + new_array[i] = array[i]; + delete [] array; + } + for (i = old_length + 1; i <= new_length; i++) + { + new_array[i].i = 0; + new_array[i].p = (void*)0; + } + new_array[0].i = new_length; + new_array[0].p = (void*)0; + io._arrays = (void*)new_array; + array = new_array; + } + return array[index+1]; +} + +long& ios::iword(int index) +{ + return get_array_element(*this, index).i; +} + +void*& ios::pword(int index) +{ + return get_array_element(*this, index).p; +} + +long ios::iword(int index) const +{ + if (index < 0) + _throw_failure(); + register struct ptr_and_long *pl_array = (ptr_and_long*)_arrays; + int len = pl_array == NULL ? 0 : pl_array[0].i; + return index >= len ? 0 : pl_array[index+1].i; +} + +void* ios::pword(int index) const +{ + if (index < 0) + _throw_failure(); + register struct ptr_and_long *pl_array = (ptr_and_long*)_arrays; + int len = pl_array == NULL ? 0 : pl_array[0].i; + return index >= len ? 0 : pl_array[index+1].p; +} diff --git a/gnu/lib/libg++/libio/iofclose.c b/gnu/lib/libg++/libio/iofclose.c new file mode 100644 index 00000000000..f3ae0964e82 --- /dev/null +++ b/gnu/lib/libg++/libio/iofclose.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 <stdlib.h> +#endif + +int +DEFUN(_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; +} diff --git a/gnu/lib/libg++/libio/iofdopen.c b/gnu/lib/libg++/libio/iofdopen.c new file mode 100644 index 00000000000..f8bc76869ad --- /dev/null +++ b/gnu/lib/libg++/libio/iofdopen.c @@ -0,0 +1,121 @@ +/* +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 * +DEFUN(_IO_fdopen, (fd, mode), + int fd AND 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; +} diff --git a/gnu/lib/libg++/libio/iofflush.c b/gnu/lib/libg++/libio/iofflush.c new file mode 100644 index 00000000000..ecb816d4198 --- /dev/null +++ b/gnu/lib/libg++/libio/iofflush.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 +DEFUN(_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; + } +} diff --git a/gnu/lib/libg++/libio/iofgetpos.c b/gnu/lib/libg++/libio/iofgetpos.c new file mode 100644 index 00000000000..5e7a8632102 --- /dev/null +++ b/gnu/lib/libg++/libio/iofgetpos.c @@ -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 "libioP.h" +#include <errno.h> +/* ANSI explicily requires setting errno to a positive value on failure. */ + +int +DEFUN(_IO_fgetpos, (fp, posp), + _IO_FILE* fp AND _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; +} diff --git a/gnu/lib/libg++/libio/iofgets.c b/gnu/lib/libg++/libio/iofgets.c new file mode 100644 index 00000000000..7b0b708a208 --- /dev/null +++ b/gnu/lib/libg++/libio/iofgets.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" + +char* +DEFUN(_IO_fgets, (buf, n, fp), + char* buf AND int n AND _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; +} diff --git a/gnu/lib/libg++/libio/iofopen.c b/gnu/lib/libg++/libio/iofopen.c new file mode 100644 index 00000000000..96910520ce7 --- /dev/null +++ b/gnu/lib/libg++/libio/iofopen.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" +#ifdef __STDC__ +#include <stdlib.h> +#endif + +_IO_FILE * +DEFUN(_IO_fopen, (filename, mode), + const char *filename AND 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; +} diff --git a/gnu/lib/libg++/libio/iofprintf.c b/gnu/lib/libg++/libio/iofprintf.c new file mode 100644 index 00000000000..11c76421809 --- /dev/null +++ b/gnu/lib/libg++/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/gnu/lib/libg++/libio/iofputs.c b/gnu/lib/libg++/libio/iofputs.c new file mode 100644 index 00000000000..7a2580f7e35 --- /dev/null +++ b/gnu/lib/libg++/libio/iofputs.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 <string.h> + +int +DEFUN(_IO_fputs, (str, fp), + const char *str AND _IO_FILE *fp) +{ + _IO_size_t len = strlen(str); + CHECK_FILE(fp, EOF); + if (_IO_sputn(fp, str, len) != len) + return EOF; + return 1; +} diff --git a/gnu/lib/libg++/libio/iofread.c b/gnu/lib/libg++/libio/iofread.c new file mode 100644 index 00000000000..8516cf30c14 --- /dev/null +++ b/gnu/lib/libg++/libio/iofread.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" + +_IO_size_t +DEFUN(_IO_fread, (buf, size, count, fp), + void *buf AND _IO_size_t size AND _IO_size_t count AND _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; +} diff --git a/gnu/lib/libg++/libio/iofscanf.c b/gnu/lib/libg++/libio/iofscanf.c new file mode 100644 index 00000000000..3e12d9b5315 --- /dev/null +++ b/gnu/lib/libg++/libio/iofscanf.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_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; +} diff --git a/gnu/lib/libg++/libio/iofsetpos.c b/gnu/lib/libg++/libio/iofsetpos.c new file mode 100644 index 00000000000..ac8a3deb12d --- /dev/null +++ b/gnu/lib/libg++/libio/iofsetpos.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 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 +DEFUN(_IO_fsetpos, (fp, posp), + _IO_FILE* fp AND 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; +} diff --git a/gnu/lib/libg++/libio/ioftell.c b/gnu/lib/libg++/libio/ioftell.c new file mode 100644 index 00000000000..d49ddaac821 --- /dev/null +++ b/gnu/lib/libg++/libio/ioftell.c @@ -0,0 +1,45 @@ +/* +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 <errno.h> +/* ANSI explicily requires setting errno to a positive value on failure. */ + +long int +DEFUN(_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); +} diff --git a/gnu/lib/libg++/libio/iofwrite.c b/gnu/lib/libg++/libio/iofwrite.c new file mode 100644 index 00000000000..eb3cd32b028 --- /dev/null +++ b/gnu/lib/libg++/libio/iofwrite.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" + +_IO_size_t +DEFUN(_IO_fwrite, (buf, size, count, fp), + const void* buf AND _IO_size_t size AND _IO_size_t count + AND _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; +} diff --git a/gnu/lib/libg++/libio/iogetdelim.c b/gnu/lib/libg++/libio/iogetdelim.c new file mode 100644 index 00000000000..ee6c0bf1f19 --- /dev/null +++ b/gnu/lib/libg++/libio/iogetdelim.c @@ -0,0 +1,99 @@ +/* +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 +DEFUN(_IO_getdelim, (lineptr, n, delimiter, fp), + char **lineptr AND _IO_size_t *n AND int delimiter AND _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; +} diff --git a/gnu/lib/libg++/libio/iogetline.c b/gnu/lib/libg++/libio/iogetline.c new file mode 100644 index 00000000000..278905d135d --- /dev/null +++ b/gnu/lib/libg++/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 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> + +/* 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/gnu/lib/libg++/libio/iogets.c b/gnu/lib/libg++/libio/iogets.c new file mode 100644 index 00000000000..f45d9c16e3f --- /dev/null +++ b/gnu/lib/libg++/libio/iogets.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" +#include <limits.h> + +char* +DEFUN(_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; +} diff --git a/gnu/lib/libg++/libio/ioignore.c b/gnu/lib/libg++/libio/ioignore.c new file mode 100644 index 00000000000..a7c2f286755 --- /dev/null +++ b/gnu/lib/libg++/libio/ioignore.c @@ -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 "libioP.h" + +int +DEFUN(_IO_ignore, (fp, n), + register _IO_FILE *fp AND _IO_size_t n) +{ + register _IO_size_t more = n; + for (;;) + { + _IO_ssize_t count = fp->_IO_read_end - fp->_IO_read_ptr; + if (count > 0) + { + if (count > more) + count = more; + fp->_IO_read_ptr += count; + more -= count; + } + if (more == 0 || __underflow(fp) == EOF) + break; + } + return n - more; +} diff --git a/gnu/lib/libg++/libio/iolibio.h b/gnu/lib/libg++/libio/iolibio.h new file mode 100644 index 00000000000..e5de77ea85c --- /dev/null +++ b/gnu/lib/libg++/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/gnu/lib/libg++/libio/iomanip.cc b/gnu/lib/libg++/libio/iomanip.cc new file mode 100644 index 00000000000..fddba55a2b9 --- /dev/null +++ b/gnu/lib/libg++/libio/iomanip.cc @@ -0,0 +1,90 @@ +/* This is part of libio/iostream, providing -*- C++ -*- input/output. +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. */ + +#ifdef __GNUG__ +#pragma implementation +#endif + +#include "iomanip.h" + + +// Those functions are called through a pointer, +// thus it does not make sense, to inline them. + +ios & __iomanip_setbase (ios& i, int n) +{ + ios::fmtflags b; + switch (n) + { + case 8: + b = ios::oct; break; + case 10: + b = ios::dec; break; + case 16: + b = ios::hex; break; + default: + b = 0; + } + i.setf(b, ios::basefield); + return i; +} + +ios & __iomanip_setfill (ios& i, int n) +{ + //FIXME if ( i.flags() & ios::widechar ) + i.fill( (char) n); + //FIXME else + //FIXME i.fill( (wchar) n); + return i; +} + +ios & __iomanip_setprecision (ios& i, int n) +{ + i.precision(n); + return i; +} +ios & __iomanip_setw (ios& i, int n) +{ + i.width(n); + return i; +} + +ios & __iomanip_setiosflags (ios& i, ios::fmtflags n) +{ + i.setf(n,n); + return i; +} + +ios & __iomanip_resetiosflags (ios& i, ios::fmtflags n) +{ + i.setf(0,n); + return i; +} + +template class smanip<int>; +template class smanip<ios::fmtflags>; +template istream& operator>>(istream&, const smanip<int>&); +template istream& operator>>(istream&, const smanip<ios::fmtflags>&); +template ostream& operator<<(ostream&, const smanip<int>&); +template ostream& operator<<(ostream&, const smanip<ios::fmtflags>&); diff --git a/gnu/lib/libg++/libio/iomanip.h b/gnu/lib/libg++/libio/iomanip.h new file mode 100644 index 00000000000..fe1156569b4 --- /dev/null +++ b/gnu/lib/libg++/libio/iomanip.h @@ -0,0 +1,165 @@ +/* This is part of libio/iostream, providing -*- C++ -*- input/output. +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. */ + +#ifndef _IOMANIP_H +#ifdef __GNUG__ +#pragma interface +#endif +#define _IOMANIP_H + +#include <iostream.h> + +extern "C++" { +//----------------------------------------------------------------------------- +// Parametrized Manipulators as specified by ANSI draft +//----------------------------------------------------------------------------- + +//----------------------------------------------------------------------------- +// Stream Manipulators +//----------------------------------------------------------------------------- +// +template<class TP> class smanip; // TP = Type Param + +template<class TP> class sapp { + ios& (*_f)(ios&, TP); +public: + sapp(ios& (*f)(ios&, TP)) : _f(f) {} + // + smanip<TP> operator()(TP a) + { return smanip<TP>(_f, a); } +}; + +template <class TP> class smanip { + ios& (*_f)(ios&, TP); + TP _a; +public: + smanip(ios& (*f)(ios&, TP), TP a) : _f(f), _a(a) {} + // + friend + istream& operator>>(istream& i, const smanip<TP>& m); + friend + ostream& operator<<(ostream& o, const smanip<TP>& m); +}; + +#ifdef __GNUG__ +extern template class smanip<int>; +extern template class smanip<ios::fmtflags>; +#endif + +template<class TP> +inline istream& operator>>(istream& i, const smanip<TP>& m) +{ (*m._f)(i, m._a); return i; } + +template<class TP> +inline ostream& operator<<(ostream& o, const smanip<TP>& m) +{ (*m._f)(o, m._a); return o;} + +#ifdef __GNUG__ +extern template istream& operator>>(istream&, const smanip<int>&); +extern template istream& operator>>(istream&, const smanip<ios::fmtflags>&); +extern template ostream& operator<<(ostream&, const smanip<int>&); +extern template ostream& operator<<(ostream&, const smanip<ios::fmtflags>&); +#endif + +//----------------------------------------------------------------------------- +// Input-Stream Manipulators +//----------------------------------------------------------------------------- +// +template<class TP> class imanip; + +template<class TP> class iapp { + istream& (*_f)(istream&, TP); +public: + iapp(istream& (*f)(istream&,TP)) : _f(f) {} + // + imanip<TP> operator()(TP a) + { return imanip<TP>(_f, a); } +}; + +template <class TP> class imanip { + istream& (*_f)(istream&, TP); + TP _a; +public: + imanip(istream& (*f)(istream&, TP), TP a) : _f(f), _a(a) {} + // + friend + istream& operator>>(istream& i, const imanip<TP>& m); +}; + +template <class TP> +inline istream& operator>>(istream& i, const imanip<TP>& m) +{ return (*m._f)( i, m._a); } + +//----------------------------------------------------------------------------- +// Output-Stream Manipulators +//----------------------------------------------------------------------------- +// +template<class TP> class omanip; + +template<class TP> class oapp { + ostream& (*_f)(ostream&, TP); +public: + oapp(ostream& (*f)(ostream&,TP)) : _f(f) {} + // + omanip<TP> operator()(TP a) + { return omanip<TP>(_f, a); } +}; + +template <class TP> class omanip { + ostream& (*_f)(ostream&, TP); + TP _a; +public: + omanip(ostream& (*f)(ostream&, TP), TP a) : _f(f), _a(a) {} + // + friend + ostream& operator<<(ostream& o, const omanip<TP>& m); +}; + +template <class TP> +inline ostream& operator<<(ostream& o, const omanip<TP>& m) +{ return (*m._f)(o, m._a); } + +//----------------------------------------------------------------------------- +// Available Manipulators +//----------------------------------------------------------------------------- + +// +// Macro to define an iomanip function, with one argument +// The underlying function is `__iomanip_<name>' +// +#define __DEFINE_IOMANIP_FN1(type,param,function) \ + extern ios& __iomanip_##function (ios&, param); \ + inline type<param> function (param n) \ + { return type<param> (__iomanip_##function, n); } + +__DEFINE_IOMANIP_FN1( smanip, int, setbase) +__DEFINE_IOMANIP_FN1( smanip, int, setfill) +__DEFINE_IOMANIP_FN1( smanip, int, setprecision) +__DEFINE_IOMANIP_FN1( smanip, int, setw) + +__DEFINE_IOMANIP_FN1( smanip, ios::fmtflags, resetiosflags) +__DEFINE_IOMANIP_FN1( smanip, ios::fmtflags, setiosflags) +} // extern "C++" + +#endif /*!_IOMANIP_H*/ diff --git a/gnu/lib/libg++/libio/iopadn.c b/gnu/lib/libg++/libio/iopadn.c new file mode 100644 index 00000000000..0e502b712c3 --- /dev/null +++ b/gnu/lib/libg++/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 this library; see the file COPYING. If not, write to the Free +Software Foundation, 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. + +As a special exception, if you link this library with files +compiled with a GNU compiler to produce an executable, this does not cause +the resulting executable to be covered by the GNU General Public License. +This exception does not however invalidate any other reasons why +the executable file might be covered by the GNU General Public License. */ + +#include "libioP.h" + +#define PADSIZE 16 +static 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/gnu/lib/libg++/libio/ioperror.c b/gnu/lib/libg++/libio/ioperror.c new file mode 100644 index 00000000000..55d822b63a6 --- /dev/null +++ b/gnu/lib/libg++/libio/ioperror.c @@ -0,0 +1,22 @@ +#include "libioP.h" +#include <errno.h> +#include <string.h> +#ifndef errno +extern int errno; +#endif + +#ifndef _IO_strerror +extern char* _IO_strerror __P((int)); +#endif + +void +DEFUN(_IO_perror, (s), + const char *s) +{ + char *error = _IO_strerror (errno); + + if (s != NULL && *s != '\0') + _IO_fprintf (_IO_stderr, "%s:", s); + + _IO_fprintf (_IO_stderr, "%s\n", error ? error : ""); +} diff --git a/gnu/lib/libg++/libio/iopopen.c b/gnu/lib/libg++/libio/iopopen.c new file mode 100644 index 00000000000..d2030028d1f --- /dev/null +++ b/gnu/lib/libg++/libio/iopopen.c @@ -0,0 +1,222 @@ +/* +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. */ + +/* written by Per Bothner (bothner@cygnus.com) */ + +#define _POSIX_SOURCE +#include "libioP.h" +#if _IO_HAVE_SYS_WAIT +#include <signal.h> +#include <unistd.h> +#ifdef __STDC__ +#include <stdlib.h> +#endif +#include <sys/types.h> +#include <sys/wait.h> + +#ifndef _IO_fork +#define _IO_fork vfork /* defined in libiberty, if needed */ +_IO_pid_t _IO_fork(); +#endif + +#endif /* _IO_HAVE_SYS_WAIT */ + +#ifndef _IO_pipe +#define _IO_pipe pipe +extern int _IO_pipe(); +#endif + +#ifndef _IO_dup2 +#define _IO_dup2 dup2 +extern int _IO_dup2(); +#endif + +#ifndef _IO_waitpid +#define _IO_waitpid waitpid +#endif + +#ifndef _IO_execl +#define _IO_execl execl +#endif +#ifndef _IO__exit +#define _IO__exit _exit +#endif + +struct _IO_proc_file +{ + struct _IO_FILE_plus file; + /* Following fields must match those in class procbuf (procbuf.h) */ + _IO_pid_t pid; + struct _IO_proc_file *next; +}; +typedef struct _IO_proc_file _IO_proc_file; + +static struct _IO_proc_file *proc_file_chain = NULL; + +_IO_FILE * +DEFUN(_IO_proc_open, (fp, command, mode), + _IO_FILE* fp AND const char *command AND const char *mode) +{ +#if _IO_HAVE_SYS_WAIT + int read_or_write; + int pipe_fds[2]; + int parent_end, child_end; + _IO_pid_t child_pid; + if (_IO_file_is_open(fp)) + return NULL; + if (_IO_pipe(pipe_fds) < 0) + return NULL; + if (mode[0] == 'r') + { + parent_end = pipe_fds[0]; + child_end = pipe_fds[1]; + read_or_write = _IO_NO_WRITES; + } + else + { + parent_end = pipe_fds[1]; + child_end = pipe_fds[0]; + read_or_write = _IO_NO_READS; + } + ((_IO_proc_file*)fp)->pid = child_pid = _IO_fork(); + if (child_pid == 0) + { + int child_std_end = mode[0] == 'r' ? 1 : 0; + _IO_close(parent_end); + if (child_end != child_std_end) + { + _IO_dup2(child_end, child_std_end); + _IO_close(child_end); + } + /* Posix.2: "popen() shall ensure that any streams from previous + popen() calls that remain open in the parent process are closed + in the new child process." */ + while (proc_file_chain) + { + _IO_close (_IO_fileno ((_IO_FILE *) proc_file_chain)); + proc_file_chain = proc_file_chain->next; + } + + _IO_execl("/bin/sh", "sh", "-c", command, NULL); + _IO__exit(127); + } + _IO_close(child_end); + if (child_pid < 0) + { + _IO_close(parent_end); + return NULL; + } + _IO_fileno(fp) = parent_end; + + /* Link into proc_file_chain. */ + ((_IO_proc_file*)fp)->next = proc_file_chain; + proc_file_chain = (_IO_proc_file*)fp; + + _IO_mask_flags (fp, read_or_write, _IO_NO_READS|_IO_NO_WRITES); + return fp; +#else /* !_IO_HAVE_SYS_WAIT */ + return NULL; +#endif +} + +_IO_FILE * +DEFUN(_IO_popen, (command, mode), + const char *command AND const char *mode) +{ + _IO_proc_file *fpx = (_IO_proc_file*)malloc(sizeof(_IO_proc_file)); + _IO_FILE *fp = (_IO_FILE*)fpx; + if (fp == NULL) + return NULL; + _IO_init(fp, 0); + _IO_JUMPS(fp) = &_IO_proc_jumps; + _IO_file_init(fp); +#if !_IO_UNIFIED_JUMPTABLES + ((struct _IO_FILE_plus*)fp)->vtable = NULL; +#endif + if (_IO_proc_open (fp, command, mode) != NULL) + return fp; + free (fpx); + return NULL; +} + +int +DEFUN(_IO_proc_close, (fp), + _IO_FILE *fp) +{ + /* This is not name-space clean. FIXME! */ +#if _IO_HAVE_SYS_WAIT + int wstatus; + _IO_proc_file **ptr = &proc_file_chain; + _IO_pid_t wait_pid; + int status = -1; + + /* Unlink from proc_file_chain. */ + for ( ; *ptr != NULL; ptr = &(*ptr)->next) + { + if (*ptr == (_IO_proc_file*)fp) + { + *ptr = (*ptr)->next; + status = 0; + break; + } + } + + if (status < 0 || _IO_close(_IO_fileno(fp)) < 0) + return -1; + /* POSIX.2 Rationale: "Some historical implementations either block + or ignore the signals SIGINT, SIGQUIT, and SIGHUP while waiting + for the child process to terminate. Since this behavior is not + described in POSIX.2, such implementations are not conforming." */ + do + { + wait_pid = _IO_waitpid (((_IO_proc_file*)fp)->pid, &wstatus, 0); + } while (wait_pid == -1 && errno == EINTR); + if (wait_pid == -1) + return -1; + return wstatus; +#else /* !_IO_HAVE_SYS_WAIT */ + return -1; +#endif +} + +struct _IO_jump_t _IO_proc_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_proc_close), + JUMP_INIT(stat, _IO_file_stat) +}; diff --git a/gnu/lib/libg++/libio/ioprims.c b/gnu/lib/libg++/libio/ioprims.c new file mode 100644 index 00000000000..faa69e0feff --- /dev/null +++ b/gnu/lib/libg++/libio/ioprims.c @@ -0,0 +1,72 @@ +/* +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. */ + +/* 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 <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/gnu/lib/libg++/libio/ioprintf.c b/gnu/lib/libg++/libio/ioprintf.c new file mode 100644 index 00000000000..0b99c2a6637 --- /dev/null +++ b/gnu/lib/libg++/libio/ioprintf.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_printf +#ifdef __STDC__ + (const char* format, ...) +#else +(format, va_alist) char *format; va_dcl +#endif +{ + int ret; + va_list args; + _IO_va_start(args, format); + ret = _IO_vfprintf(_IO_stdout, format, args); + va_end(args); + return ret; +} diff --git a/gnu/lib/libg++/libio/ioputs.c b/gnu/lib/libg++/libio/ioputs.c new file mode 100644 index 00000000000..f0a81642853 --- /dev/null +++ b/gnu/lib/libg++/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 +DEFUN(_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; +} diff --git a/gnu/lib/libg++/libio/ioscanf.c b/gnu/lib/libg++/libio/ioscanf.c new file mode 100644 index 00000000000..405d1e2eb0f --- /dev/null +++ b/gnu/lib/libg++/libio/ioscanf.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_scanf +#ifdef __STDC__ + (const char* format, ...) +#else +(format, va_alist) char *format; va_dcl +#endif +{ + int ret; + va_list args; + _IO_va_start(args, format); + ret = _IO_vfscanf(_IO_stdin, format, args, NULL); + va_end(args); + return ret; +} diff --git a/gnu/lib/libg++/libio/ioseekoff.c b/gnu/lib/libg++/libio/ioseekoff.c new file mode 100644 index 00000000000..06f4b9d2fe1 --- /dev/null +++ b/gnu/lib/libg++/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 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_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/gnu/lib/libg++/libio/ioseekpos.c b/gnu/lib/libg++/libio/ioseekpos.c new file mode 100644 index 00000000000..1884f9df8f7 --- /dev/null +++ b/gnu/lib/libg++/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 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_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/gnu/lib/libg++/libio/iosetbuffer.c b/gnu/lib/libg++/libio/iosetbuffer.c new file mode 100644 index 00000000000..eb78d75d9ab --- /dev/null +++ b/gnu/lib/libg++/libio/iosetbuffer.c @@ -0,0 +1,36 @@ +/* +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 +DEFUN(_IO_setbuffer, (fp, buf, size), + _IO_FILE *fp AND char *buf AND _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/gnu/lib/libg++/libio/iosetvbuf.c b/gnu/lib/libg++/libio/iosetvbuf.c new file mode 100644 index 00000000000..cc664b41910 --- /dev/null +++ b/gnu/lib/libg++/libio/iosetvbuf.c @@ -0,0 +1,77 @@ +/* +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 +DEFUN(_IO_setvbuf, (fp, buf, mode, size), + _IO_FILE* fp AND char* buf AND int mode AND _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/gnu/lib/libg++/libio/iosprintf.c b/gnu/lib/libg++/libio/iosprintf.c new file mode 100644 index 00000000000..b873eb4455d --- /dev/null +++ b/gnu/lib/libg++/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/gnu/lib/libg++/libio/iosscanf.c b/gnu/lib/libg++/libio/iosscanf.c new file mode 100644 index 00000000000..58868778c48 --- /dev/null +++ b/gnu/lib/libg++/libio/iosscanf.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_sscanf +#ifdef __STDC__ + (const 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_vsscanf(string, format, args); + va_end(args); + return ret; +} diff --git a/gnu/lib/libg++/libio/iostdio.h b/gnu/lib/libg++/libio/iostdio.h new file mode 100644 index 00000000000..8f90d9eedfe --- /dev/null +++ b/gnu/lib/libg++/libio/iostdio.h @@ -0,0 +1,110 @@ +/* +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. */ + +/* This file defines a stdio-like environment, except that it avoid + link-time name clashes with an existing stdio. + It allows for testing the libio using stdio-using programs + with an incompatible libc.a. + It is not predantically correct - e.g. some macros are used + that may evaluate a stream argument more than once. */ + +#ifndef _IOSTDIO_H +#define _IOSTDIO_H + +#include "iolibio.h" + +typedef _IO_FILE FILE; +#ifndef EOF +#define EOF (-1) +#endif +#ifndef BUFSIZ +#define BUFSIZ 1024 +#endif + +/* #define size_t, fpos_t L_tmpname TMP_MAX */ + +#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 stdin _IO_stdin +#define stdout _IO_stdout +#define stderr _IO_stderr + +#define getc(_fp) _IO_getc(_fp) +#define putc(_ch, _fp) _IO_putc(_ch, _fp) + +#define clearerr _IO_clearerr +#define fclose _IO_fclose +#define feof _IO_feof +#define ferror _IO_ferror +#define fflush _IO_fflush +#define fgetc(__fp) _IO_getc(_fp) +#define fgetpos _IO_fgetpos +#define fgets _IO_fgets +#define fopen _IO_fopen +#define fprintf _IO_fprintf +#define fputc(_ch, _fp) _IO_putc(_ch, _fp) +#define fputs _IO_fputs +#define fread _IO_fread +#define freopen _IO_freopen +#define fscanf _IO_fscanf +#define fseek _IO_fseek +#define fsetpos _IO_fsetpos +#define ftell _IO_ftell +#define fwrite _IO_fwrite +#define gets _IO_gets +#define perror _IO_perror +#define printf _IO_printf +#define puts _IO_puts +#define remove ??? __P((const char*)) +#define rename ??? __P((const char* _old, const char* _new)) +#define rewind _IO_rewind +#define scanf _IO_scanf +#define setbuf _IO_setbuf +#define setbuffer _IO_setbuffer +#define setvbuf _IO_setvbuf +#define sprintf _IO_sprintf +#define sscanf _IO_sscanf +#define tmpfile ??? __P((void)) +#define tmpnam ??? __P((char*)) +#define ungetc _IO_ungetc +#define vfprintf _IO_vfprintf +#define vprintf(__fmt, __args) vfprintf(stdout, __fmt, __args) +#define vsprintf _IO_vsprintf + +#if !defined(__STRICT_ANSI__) || defined(_POSIX_SOURCE) +#define fdopen _IO_fdopen +#define fileno _IO_fileno +#define popen _IO_popen +#define pclose _IO_pclose +#define setbuf _IO_setbuf +#define setlinebuf _IO_setlinebuf +#endif + +#endif /* _IOSTDIO_H */ diff --git a/gnu/lib/libg++/libio/iostream.cc b/gnu/lib/libg++/libio/iostream.cc new file mode 100644 index 00000000000..3bdfd59a054 --- /dev/null +++ b/gnu/lib/libg++/libio/iostream.cc @@ -0,0 +1,821 @@ +/* This is part of libio/iostream, providing -*- C++ -*- input/output. +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. */ + +/* Written by Per Bothner (bothner@cygnus.com). */ + +#ifdef __GNUC__ +#pragma implementation +#endif +#define _STREAM_COMPAT +#include <iostream.h> +#include "libioP.h" +#include <stdio.h> /* Needed for sprintf */ +#include <ctype.h> +#include <string.h> +#include <limits.h> +#include "floatio.h" + +#define BUF (MAXEXP+MAXFRACT+1) /* + decimal point */ + +//#define isspace(ch) ((ch)==' ' || (ch)=='\t' || (ch)=='\n') + +istream::istream(streambuf *sb, ostream* tied) +{ + init (sb, tied); + _gcount = 0; +} + +int skip_ws(streambuf* sb) +{ + int ch; + for (;;) { + ch = sb->sbumpc(); + if (ch == EOF || !isspace(ch)) + return ch; + } +} + +istream& istream::get(char& c) +{ + if (ipfx1()) { + int ch = _strbuf->sbumpc(); + if (ch == EOF) { + set(ios::eofbit|ios::failbit); + _gcount = 0; + } + else { + c = (char)ch; + _gcount = 1; + } + } + else + _gcount = 0; + return *this; +} + +int istream::peek() +{ + if (!good()) + return EOF; + if (_tie && rdbuf()->in_avail() == 0) + _tie->flush(); + int ch = _strbuf->sgetc(); + if (ch == EOF) + set(ios::eofbit); + return ch; +} + +istream& istream::ignore(int n /* = 1 */, int delim /* = EOF */) +{ + _gcount = 0; + if (ipfx1()) { + register streambuf* sb = _strbuf; + if (delim == EOF) { + _gcount = sb->ignore(n); + return *this; + } + for (;;) { +#if 0 + if (n != MAXINT) // FIXME +#endif + if (--n < 0) + break; + int ch = sb->sbumpc(); + if (ch == EOF) { + set(ios::eofbit|ios::failbit); + break; + } + _gcount++; + if (ch == delim) + break; + } + } + return *this; +} + +istream& istream::read(char *s, streamsize n) +{ + if (ipfx1()) { + _gcount = _strbuf->sgetn(s, n); + if (_gcount != n) + set(ios::failbit|ios::eofbit); + } + else + _gcount = 0; + return *this; +} + +int +istream::sync () +{ + streambuf *sb = rdbuf (); + if (sb == NULL) + return EOF; + if (sb->sync ()) // Later: pubsync + { + setstate (ios::badbit); + return EOF; + } + else + return 0; +} + +istream& istream::seekg(streampos pos) +{ + pos = _strbuf->pubseekpos(pos, ios::in); + if (pos == streampos(EOF)) + set(ios::badbit); + return *this; +} + +istream& istream::seekg(streamoff off, _seek_dir dir) +{ + streampos pos = _IO_seekoff (_strbuf, off, (int) dir, _IOS_INPUT); + if (pos == streampos(EOF)) + set(ios::badbit); + return *this; +} + +streampos istream::tellg() +{ +#if 0 + streampos pos = _strbuf->pubseekoff(0, ios::cur, ios::in); +#else + streampos pos = _IO_seekoff (_strbuf, 0, _IO_seek_cur, _IOS_INPUT); +#endif + if (pos == streampos(EOF)) + set(ios::badbit); + return pos; +} + +istream& istream::operator>>(char& c) +{ + if (ipfx0()) { + int ch = _strbuf->sbumpc(); + if (ch == EOF) + set(ios::eofbit|ios::failbit); + else + c = (char)ch; + } + return *this; +} + +istream& +istream::operator>> (char* ptr) +{ + register char *p = ptr; + int w = width(0); + if (ipfx0()) + { + register streambuf* sb = _strbuf; + for (;;) + { + int ch = sb->sbumpc(); + if (ch == EOF) + { + set(ios::eofbit); + break; + } + else if (isspace(ch) || w == 1) + { + sb->sputbackc(ch); + break; + } + else *p++ = ch; + w--; + } + if (p == ptr) + set(ios::failbit); + } + *p = '\0'; + return *this; +} + +#if defined(__GNUC__) && !defined(__STRICT_ANSI__) +#define LONGEST long long +#else +#define LONGEST long +#endif + +static int read_int(istream& stream, unsigned LONGEST& val, int& neg) +{ + if (!stream.ipfx0()) + return 0; + register streambuf* sb = stream.rdbuf(); + int base = 10; + int ndigits = 0; + register int ch = skip_ws(sb); + if (ch == EOF) + goto eof_fail; + neg = 0; + if (ch == '+') { + ch = skip_ws(sb); + } + else if (ch == '-') { + neg = 1; + ch = skip_ws(sb); + } + if (ch == EOF) goto eof_fail; + if (!(stream.flags() & ios::basefield)) { + if (ch == '0') { + ch = sb->sbumpc(); + if (ch == EOF) { + val = 0; + return 1; + } + if (ch == 'x' || ch == 'X') { + base = 16; + ch = sb->sbumpc(); + if (ch == EOF) goto eof_fail; + } + else { + sb->sputbackc(ch); + base = 8; + ch = '0'; + } + } + } + else if ((stream.flags() & ios::basefield) == ios::hex) + base = 16; + else if ((stream.flags() & ios::basefield) == ios::oct) + base = 8; + val = 0; + for (;;) { + if (ch == EOF) + break; + int digit; + if (ch >= '0' && ch <= '9') + digit = ch - '0'; + else if (ch >= 'A' && ch <= 'F') + digit = ch - 'A' + 10; + else if (ch >= 'a' && ch <= 'f') + digit = ch - 'a' + 10; + else + digit = 999; + if (digit >= base) { + sb->sputbackc(ch); + if (ndigits == 0) + goto fail; + else + return 1; + } + ndigits++; + val = base * val + digit; + ch = sb->sbumpc(); + } + return 1; + fail: + stream.set(ios::failbit); + return 0; + eof_fail: + stream.set(ios::failbit|ios::eofbit); + return 0; +} + +#define READ_INT(TYPE) \ +istream& istream::operator>>(TYPE& i)\ +{\ + unsigned LONGEST val; int neg;\ + if (read_int(*this, val, neg)) {\ + if (neg) val = -val;\ + i = (TYPE)val;\ + }\ + return *this;\ +} + +READ_INT(short) +READ_INT(unsigned short) +READ_INT(int) +READ_INT(unsigned int) +READ_INT(long) +READ_INT(unsigned long) +#if defined(__GNUC__) && !defined(__STRICT_ANSI__) +READ_INT(long long) +READ_INT(unsigned long long) +#endif +#if _G_HAVE_BOOL +READ_INT(bool) +#endif + +istream& istream::operator>>(long double& x) +{ + if (ipfx0()) + scan("%lg", &x); + return *this; +} + +istream& istream::operator>>(double& x) +{ + if (ipfx0()) + scan("%lg", &x); + return *this; +} + +istream& istream::operator>>(float& x) +{ + if (ipfx0()) + scan("%g", &x); + return *this; +} + +istream& istream::operator>>(register streambuf* sbuf) +{ + if (ipfx0()) { + register streambuf* inbuf = rdbuf(); + // FIXME: Should optimize! + for (;;) { + register int ch = inbuf->sbumpc(); + if (ch == EOF) { + set(ios::eofbit); + break; + } + if (sbuf->sputc(ch) == EOF) { + set(ios::failbit); + break; + } + } + } + return *this; +} + +ostream& ostream::operator<<(char c) +{ + if (opfx()) { +#if 1 + // This is what the cfront implementation does. + if (_strbuf->sputc(c) == EOF) + goto failed; +#else + // This is what cfront documentation and current ANSI drafts say. + int w = width(0); + char fill_char = fill(); + register int padding = w > 0 ? w - 1 : 0; + register streambuf *sb = _strbuf; + if (!(flags() & ios::left) && padding) // Default adjustment. + if (_IO_padn(sb, fill_char, padding) < padding) + goto failed; + if (sb->sputc(c) == EOF) + goto failed; + if (flags() & ios::left && padding) // Left adjustment. + if (_IO_padn(sb, fill_char, padding) < padding) + goto failed; +#endif + osfx(); + } + return *this; + failed: + set(ios::badbit); + osfx(); + return *this; +} + +/* Write VAL on STREAM. + If SIGN<0, val is the absolute value of a negative number. + If SIGN>0, val is a signed non-negative number. + If SIGN==0, val is unsigned. */ + +static void write_int(ostream& stream, unsigned LONGEST val, int sign) +{ +#define WRITE_BUF_SIZE (10 + sizeof(unsigned LONGEST) * 3) + char buf[WRITE_BUF_SIZE]; + register char *buf_ptr = buf+WRITE_BUF_SIZE; // End of buf. + char *show_base = ""; + int show_base_len = 0; + int show_pos = 0; // If 1, print a '+'. + + // Now do the actual conversion, placing the result at the *end* of buf. + // Note that we use separate code for decimal, octal, and hex, + // so we can divide by optimizable constants. + if ((stream.flags() & ios::basefield) == ios::oct) { // Octal + do { + *--buf_ptr = (val & 7) + '0'; + val = val >> 3; + } while (val != 0); + if ((stream.flags() & ios::showbase) && (*buf_ptr != '0')) + *--buf_ptr = '0'; + } + else if ((stream.flags() & ios::basefield) == ios::hex) { // Hex + char *xdigs = (stream.flags() & ios::uppercase) ? "0123456789ABCDEF0X" + : "0123456789abcdef0x"; + do { + *--buf_ptr = xdigs[val & 15]; + val = val >> 4; + } while (val != 0); + if ((stream.flags() & ios::showbase)) { + show_base = xdigs + 16; // Either "0X" or "0x". + show_base_len = 2; + } + } + else { // Decimal +#if defined(__GNUC__) && !defined(__STRICT_ANSI__) + // Optimization: Only use long long when we need to. + while (val > UINT_MAX) { + *--buf_ptr = (val % 10) + '0'; + val /= 10; + } + // Use more efficient (int) arithmetic for the rest. + register unsigned int ival = (unsigned int)val; +#else + register unsigned LONGEST ival = val; +#endif + do { + *--buf_ptr = (ival % 10) + '0'; + ival /= 10; + } while (ival != 0); + if (sign > 0 && (stream.flags() & ios::showpos)) + show_pos=1; + } + + int buf_len = buf+WRITE_BUF_SIZE - buf_ptr; + int w = stream.width(0); + + // Calculate padding. + int len = buf_len+show_pos; + if (sign < 0) len++; + len += show_base_len; + int padding = len > w ? 0 : w - len; + + // Do actual output. + register streambuf* sbuf = stream.rdbuf(); + ios::fmtflags pad_kind = + stream.flags() & (ios::left|ios::right|ios::internal); + char fill_char = stream.fill(); + if (padding > 0 + && pad_kind != (ios::fmtflags)ios::left + && pad_kind != (ios::fmtflags)ios::internal) // Default (right) adjust. + if (_IO_padn(sbuf, fill_char, padding) < padding) + goto failed; + if (sign < 0 || show_pos) + { + char ch = sign < 0 ? '-' : '+'; + if (sbuf->sputc(ch) < 0) + goto failed; + } + if (show_base_len) + if (_IO_sputn(sbuf, show_base, show_base_len) <= 0) + goto failed; + if (pad_kind == (ios::fmtflags)ios::internal && padding > 0) + if (_IO_padn(sbuf, fill_char, padding) < padding) + goto failed; + if (_IO_sputn (sbuf, buf_ptr, buf_len) != buf_len) + goto failed; + if (pad_kind == (ios::fmtflags)ios::left && padding > 0) // Left adjustment + if (_IO_padn(sbuf, fill_char, padding) < padding) + goto failed; + stream.osfx(); + return; + failed: + stream.set(ios::badbit); + stream.osfx(); +} + +ostream& ostream::operator<<(int n) +{ + if (opfx()) { + int sign = 1; + unsigned int abs_n = (unsigned)n; + if (n < 0 && (flags() & (ios::oct|ios::hex)) == 0) + abs_n = -((unsigned)n), sign = -1; + write_int(*this, abs_n, sign); + } + return *this; +} + +ostream& ostream::operator<<(unsigned int n) +{ + if (opfx()) + write_int(*this, n, 0); + return *this; +} + + +ostream& ostream::operator<<(long n) +{ + if (opfx()) { + int sign = 1; + unsigned long abs_n = (unsigned long)n; + if (n < 0 && (flags() & (ios::oct|ios::hex)) == 0) + abs_n = -((unsigned long)n), sign = -1; + write_int(*this, abs_n, sign); + } + return *this; +} + +ostream& ostream::operator<<(unsigned long n) +{ + if (opfx()) + write_int(*this, n, 0); + return *this; +} + +#if defined(__GNUC__) && !defined(__STRICT_ANSI__) +ostream& ostream::operator<<(long long n) +{ + if (opfx()) { + int sign = 1; + unsigned long long abs_n = (unsigned long long)n; + if (n < 0 && (flags() & (ios::oct|ios::hex)) == 0) + abs_n = -((unsigned long long)n), sign = -1; + write_int(*this, abs_n, sign); + } + return *this; +} + + +ostream& ostream::operator<<(unsigned long long n) +{ + if (opfx()) + write_int(*this, n, 0); + return *this; +} +#endif /*__GNUC__*/ + +ostream& ostream::operator<<(double n) +{ + if (opfx()) { + // Uses __cvt_double (renamed from static cvt), in Chris Torek's + // stdio implementation. The setup code uses the same logic + // as in __vsbprintf.C (also based on Torek's code). + int format_char; + if ((flags() & ios::floatfield) == ios::fixed) + format_char = 'f'; + else if ((flags() & ios::floatfield) == ios::scientific) + format_char = flags() & ios::uppercase ? 'E' : 'e'; + else + format_char = flags() & ios::uppercase ? 'G' : 'g'; + + int prec = precision(); + if (prec <= 0 && !(flags() & ios::fixed)) + prec = 6; /* default */ + + // Do actual conversion. +#ifdef _IO_USE_DTOA + if (_IO_outfloat(n, rdbuf(), format_char, width(0), + prec, flags(), + flags() & ios::showpos ? '+' : 0, + fill()) < 0) + set(ios::badbit|ios::failbit); // ?? +#else + int fpprec = 0; // 'Extra' (suppressed) floating precision. + if (prec > MAXFRACT) { + if (flags() & (ios::fixed|ios::scientific) & ios::showpos) + fpprec = prec - MAXFRACT; + prec = MAXFRACT; + } + int negative; + char buf[BUF]; + int sign = '\0'; + char *cp = buf; + *cp = 0; + int size = __cvt_double(n, prec, + flags() & ios::showpoint ? 0x80 : 0, + &negative, + format_char, cp, buf + sizeof(buf)); + if (negative) sign = '-'; + else if (flags() & ios::showpos) sign = '+'; + if (*cp == 0) + cp++; + + // Calculate padding. + int fieldsize = size + fpprec; + if (sign) fieldsize++; + int padding = 0; + int w = width(0); + if (fieldsize < w) + padding = w - fieldsize; + + // Do actual output. + register streambuf* sbuf = rdbuf(); + register i; + char fill_char = fill(); + ios::fmtflags pad_kind = + flags() & (ios::left|ios::right|ios::internal); + if (pad_kind != (ios::fmtflags)ios::left // Default (right) adjust. + && pad_kind != (ios::fmtflags)ios::internal) + for (i = padding; --i >= 0; ) sbuf->sputc(fill_char); + if (sign) + sbuf->sputc(sign); + if (pad_kind == (ios::fmtflags)ios::internal) + for (i = padding; --i >= 0; ) sbuf->sputc(fill_char); + + // Emit the actual concented field, followed by extra zeros. + _IO_sputn (sbuf, cp, size); + for (i = fpprec; --i >= 0; ) sbuf->sputc('0'); + + if (pad_kind == (ios::fmtflags)ios::left) // Left adjustment + for (i = padding; --i >= 0; ) sbuf->sputc(fill_char); +#endif + osfx(); + } + return *this; +} + +ostream& ostream::operator<<(const char *s) +{ + if (opfx()) + { + if (s == NULL) + s = "(null)"; + int len = strlen(s); + int w = width(0); +// FIXME: Should we: if (w && len>w) len = w; + char fill_char = fill(); + register streambuf *sbuf = rdbuf(); + register int padding = w > len ? w - len : 0; + if (!(flags() & ios::left) && padding > 0) // Default adjustment. + if (_IO_padn(sbuf, fill_char, padding) != padding) + goto failed; + if (_IO_sputn (sbuf, s, len) != len) + goto failed; + if (flags() & ios::left && padding > 0) // Left adjustment. + if (_IO_padn(sbuf, fill_char, padding) != padding) + goto failed; + osfx(); + } + return *this; + failed: + set(ios::badbit); + osfx(); + return *this; +} + +#if 0 +ostream& ostream::operator<<(const void *p) +{ Is in osform.cc, to avoid pulling in all of _IO_vfprintf by this file. */ } +#endif + +ostream& ostream::operator<<(register streambuf* sbuf) +{ + if (opfx()) + { + char buffer[_IO_BUFSIZ]; + register streambuf* outbuf = _strbuf; + for (;;) + { + _IO_size_t count = _IO_sgetn(sbuf, buffer, _IO_BUFSIZ); + if (count <= 0) + break; + if (_IO_sputn(outbuf, buffer, count) != count) + { + set(ios::badbit); + break; + } + } + osfx(); + } + return *this; +} + +ostream::ostream(streambuf* sb, ostream* tied) +{ + init (sb, tied); +} + +ostream& ostream::seekp(streampos pos) +{ + pos = _strbuf->pubseekpos(pos, ios::out); + if (pos == streampos(EOF)) + set(ios::badbit); + return *this; +} + +ostream& ostream::seekp(streamoff off, _seek_dir dir) +{ + streampos pos = _IO_seekoff (_strbuf, off, (int) dir, _IOS_OUTPUT); + if (pos == streampos(EOF)) + set(ios::badbit); + return *this; +} + +streampos ostream::tellp() +{ +#if 1 + streampos pos = _IO_seekoff (_strbuf, 0, _IO_seek_cur, _IOS_OUTPUT); +#else + streampos pos = _strbuf->pubseekoff(0, ios::cur, ios::out); +#endif + if (pos == streampos(EOF)) + set(ios::badbit); + return pos; +} + +ostream& ostream::flush() +{ + if (_strbuf->sync()) + set(ios::badbit); + return *this; +} + +ostream& flush(ostream& outs) +{ + return outs.flush(); +} + +istream& ws(istream& ins) +{ + if (ins.ipfx1()) { + int ch = skip_ws(ins._strbuf); + if (ch == EOF) + ins.set(ios::eofbit); + else + ins._strbuf->sputbackc(ch); + } + return ins; +} + +// Skip white-space. Return 0 on failure (EOF), or 1 on success. +// Differs from ws() manipulator in that failbit is set on EOF. +// Called by ipfx() and ipfx0() if needed. + +int istream::_skip_ws() +{ + int ch = skip_ws(_strbuf); + if (ch == EOF) { + set(ios::eofbit|ios::failbit); + return 0; + } + else { + _strbuf->sputbackc(ch); + return 1; + } +} + +ostream& ends(ostream& outs) +{ + outs.put('\0'); + return outs; +} + +ostream& endl(ostream& outs) +{ + return flush(outs.put('\n')); +} + +ostream& ostream::write(const char *s, streamsize n) +{ + if (opfx()) { + if (_IO_sputn(_strbuf, s, n) != n) + set(ios::failbit); + } + return *this; +} + +void ostream::do_osfx() +{ + if (flags() & ios::unitbuf) + flush(); + if (flags() & ios::stdio) { + fflush(stdout); + fflush(stderr); + } +} + +iostream::iostream(streambuf* sb, ostream* tied) +{ + init (sb, tied); +} + +// NOTE: extension for compatibility with old libg++. +// Not really compatible with fistream::close(). +#ifdef _STREAM_COMPAT +void ios::close() +{ + if (_strbuf->_flags & _IO_IS_FILEBUF) + ((struct filebuf*)rdbuf())->close(); + else if (_strbuf != NULL) + rdbuf()->sync(); + _strbuf = NULL; + _state = badbit; +} + +int istream::skip(int i) +{ + int old = (_flags & ios::skipws) != 0; + if (i) + _flags |= ios::skipws; + else + _flags &= ~ios::skipws; + return old; +} +#endif diff --git a/gnu/lib/libg++/libio/iostream.h b/gnu/lib/libg++/libio/iostream.h new file mode 100644 index 00000000000..fc3aaa84dd6 --- /dev/null +++ b/gnu/lib/libg++/libio/iostream.h @@ -0,0 +1,248 @@ +/* This is part of libio/iostream, providing -*- C++ -*- input/output. +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. */ + +#ifndef _IOSTREAM_H +#ifdef __GNUG__ +#pragma interface +#endif +#define _IOSTREAM_H + +#include <streambuf.h> + +extern "C++" { +class istream; class ostream; +typedef ios& (*__manip)(ios&); +typedef istream& (*__imanip)(istream&); +typedef ostream& (*__omanip)(ostream&); + +extern istream& ws(istream& ins); +extern ostream& flush(ostream& outs); +extern ostream& endl(ostream& outs); +extern ostream& ends(ostream& outs); + +class ostream : virtual public ios +{ + // NOTE: If fields are changed, you must fix _fake_ostream in stdstreams.C! + void do_osfx(); + public: + ostream() { } + ostream(streambuf* sb, ostream* tied=NULL); + int opfx() { + if (!good()) return 0; else { if (_tie) _tie->flush(); return 1;} } + void osfx() { if (flags() & (ios::unitbuf|ios::stdio)) + do_osfx(); } + ostream& flush(); + ostream& put(char c) { _strbuf->sputc(c); return *this; } +#ifdef _STREAM_COMPAT + /* Temporary binary compatibility. REMOVE IN NEXT RELEASE. */ + ostream& put(unsigned char c) { return put((char)c); } + ostream& put(signed char c) { return put((char)c); } +#endif + ostream& write(const char *s, streamsize n); + ostream& write(const unsigned char *s, streamsize n) + { return write((const char*)s, n);} + ostream& write(const signed char *s, streamsize n) + { return write((const char*)s, n);} + ostream& write(const void *s, streamsize n) + { return write((const char*)s, n);} + ostream& seekp(streampos); + ostream& seekp(streamoff, _seek_dir); + streampos tellp(); + ostream& form(const char *format ...); + ostream& vform(const char *format, _IO_va_list args); + + ostream& operator<<(char c); + ostream& operator<<(unsigned char c) { return (*this) << (char)c; } + ostream& operator<<(signed char c) { return (*this) << (char)c; } + ostream& operator<<(const char *s); + ostream& operator<<(const unsigned char *s) + { return (*this) << (const char*)s; } + ostream& operator<<(const signed char *s) + { return (*this) << (const char*)s; } + ostream& operator<<(const void *p); + ostream& operator<<(int n); + ostream& operator<<(unsigned int n); + ostream& operator<<(long n); + ostream& operator<<(unsigned long n); +#if defined(__GNUC__) && !defined(__STRICT_ANSI__) + ostream& operator<<(long long n); + ostream& operator<<(unsigned long long n); +#endif + ostream& operator<<(short n) {return operator<<((int)n);} + ostream& operator<<(unsigned short n) {return operator<<((unsigned int)n);} +#if _G_HAVE_BOOL + ostream& operator<<(bool b) { return operator<<((int)b); } +#endif + ostream& operator<<(double n); + ostream& operator<<(float n) { return operator<<((double)n); } + ostream& operator<<(long double n) { return operator<<((double)n); } + ostream& operator<<(__omanip func) { return (*func)(*this); } + ostream& operator<<(__manip func) {(*func)(*this); return *this;} + ostream& operator<<(streambuf*); +#ifdef _STREAM_COMPAT + streambuf* ostreambuf() const { return _strbuf; } +#endif +}; + +class istream : virtual public ios +{ + // NOTE: If fields are changed, you must fix _fake_istream in stdstreams.C! +protected: + _IO_size_t _gcount; + + int _skip_ws(); + public: + istream() { _gcount = 0; } + istream(streambuf* sb, ostream*tied=NULL); + istream& get(char* ptr, int len, char delim = '\n'); + istream& get(unsigned char* ptr, int len, char delim = '\n') + { return get((char*)ptr, len, delim); } + istream& get(char& c); + istream& get(unsigned char& c) { return get((char&)c); } + istream& getline(char* ptr, int len, char delim = '\n'); + istream& getline(unsigned char* ptr, int len, char delim = '\n') + { return getline((char*)ptr, len, delim); } + istream& get(signed char& c) { return get((char&)c); } + istream& get(signed char* ptr, int len, char delim = '\n') + { return get((char*)ptr, len, delim); } + istream& getline(signed char* ptr, int len, char delim = '\n') + { return getline((char*)ptr, len, delim); } + istream& read(char *ptr, streamsize n); + istream& read(unsigned char *ptr, streamsize n) + { return read((char*)ptr, n); } + istream& read(signed char *ptr, streamsize n) + { return read((char*)ptr, n); } + istream& read(void *ptr, streamsize n) + { return read((char*)ptr, n); } + istream& get(streambuf& sb, char delim = '\n'); + istream& gets(char **s, char delim = '\n'); + int ipfx(int need = 0) { + if (!good()) { set(ios::failbit); return 0; } + else { + if (_tie && (need == 0 || rdbuf()->in_avail() < need)) _tie->flush(); + if (!need && (flags() & ios::skipws)) return _skip_ws(); + else return 1; + } + } + int ipfx0() { // Optimized version of ipfx(0). + if (!good()) { set(ios::failbit); return 0; } + else { + if (_tie) _tie->flush(); + if (flags() & ios::skipws) return _skip_ws(); + else return 1; + } + } + int ipfx1() { // Optimized version of ipfx(1). + if (!good()) { set(ios::failbit); return 0; } + else { + if (_tie && rdbuf()->in_avail() == 0) _tie->flush(); + return 1; + } + } + void isfx() { } + int get() { if (!ipfx1()) return EOF; + else { int ch = _strbuf->sbumpc(); + if (ch == EOF) set(ios::eofbit); + return ch; + } } + int peek(); + _IO_size_t gcount() { return _gcount; } + istream& ignore(int n=1, int delim = EOF); + int sync (); + istream& seekg(streampos); + istream& seekg(streamoff, _seek_dir); + streampos tellg(); + istream& putback(char ch) { + if (good() && _strbuf->sputbackc(ch) == EOF) clear(ios::badbit); + return *this;} + istream& unget() { + if (good() && _strbuf->sungetc() == EOF) clear(ios::badbit); + return *this;} + istream& scan(const char *format ...); + istream& vscan(const char *format, _IO_va_list args); +#ifdef _STREAM_COMPAT + istream& unget(char ch) { return putback(ch); } + int skip(int i); + streambuf* istreambuf() const { return _strbuf; } +#endif + + istream& operator>>(char*); + istream& operator>>(unsigned char* p) { return operator>>((char*)p); } + istream& operator>>(signed char*p) { return operator>>((char*)p); } + istream& operator>>(char& c); + istream& operator>>(unsigned char& c) {return operator>>((char&)c);} + istream& operator>>(signed char& c) {return operator>>((char&)c);} + istream& operator>>(int&); + istream& operator>>(long&); +#if defined(__GNUC__) && !defined(__STRICT_ANSI__) + istream& operator>>(long long&); + istream& operator>>(unsigned long long&); +#endif + istream& operator>>(short&); + istream& operator>>(unsigned int&); + istream& operator>>(unsigned long&); + istream& operator>>(unsigned short&); +#if _G_HAVE_BOOL + istream& operator>>(bool&); +#endif + istream& operator>>(float&); + istream& operator>>(double&); + istream& operator>>(long double&); + istream& operator>>( __manip func) {(*func)(*this); return *this;} + istream& operator>>(__imanip func) { return (*func)(*this); } + istream& operator>>(streambuf*); +}; + +class iostream : public istream, public ostream +{ + public: + iostream() { } + iostream(streambuf* sb, ostream*tied=NULL); +}; + +class _IO_istream_withassign : public istream { +public: + _IO_istream_withassign& operator=(istream&); +}; + +class _IO_ostream_withassign : public ostream { +public: + _IO_ostream_withassign& operator=(ostream&); +}; + +extern _IO_istream_withassign cin; +// clog->rdbuf() == cerr->rdbuf() +extern _IO_ostream_withassign cout, cerr, clog; + +struct Iostream_init { } ; // Compatibility hack for AT&T library. + +inline ios& dec(ios& i) +{ i.setf(ios::dec, ios::dec|ios::hex|ios::oct); return i; } +inline ios& hex(ios& i) +{ i.setf(ios::hex, ios::dec|ios::hex|ios::oct); return i; } +inline ios& oct(ios& i) +{ i.setf(ios::oct, ios::dec|ios::hex|ios::oct); return i; } +} // extern "C++" + +#endif /*!_IOSTREAM_H*/ diff --git a/gnu/lib/libg++/libio/iostreamP.h b/gnu/lib/libg++/libio/iostreamP.h new file mode 100644 index 00000000000..c9c40cb6ba9 --- /dev/null +++ b/gnu/lib/libg++/libio/iostreamP.h @@ -0,0 +1,26 @@ +/* +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 "streambuf.h" +#include "libioP.h" diff --git a/gnu/lib/libg++/libio/iostrerror.c b/gnu/lib/libg++/libio/iostrerror.c new file mode 100644 index 00000000000..65aa25d5e4e --- /dev/null +++ b/gnu/lib/libg++/libio/iostrerror.c @@ -0,0 +1,12 @@ +/* This should be replaced by whatever namespace-clean + version of strerror you have available. */ + +#include "libioP.h" +extern char *strerror __P ((int)); + +char * +DEFUN(_IO_strerror, (errnum), + int errnum) +{ + return strerror(errnum); +} diff --git a/gnu/lib/libg++/libio/ioungetc.c b/gnu/lib/libg++/libio/ioungetc.c new file mode 100644 index 00000000000..033f652a067 --- /dev/null +++ b/gnu/lib/libg++/libio/ioungetc.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" + +int +DEFUN(_IO_ungetc, (c, fp), + int c AND _IO_FILE *fp) +{ + CHECK_FILE(fp, EOF); + if (c == EOF) + return EOF; + return _IO_sputbackc(fp, (unsigned char)c); +} diff --git a/gnu/lib/libg++/libio/iovfprintf.c b/gnu/lib/libg++/libio/iovfprintf.c new file mode 100644 index 00000000000..c6ba7957d71 --- /dev/null +++ b/gnu/lib/libg++/libio/iovfprintf.c @@ -0,0 +1,881 @@ +/* +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 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. + */ + + +#if defined(LIBC_SCCS) && !defined(lint) +static char sccsid[] = "%W% (Berkeley) %G%"; +#endif /* LIBC_SCCS and not lint */ + +/* + * Actual printf innards. + * + * This code is large and complicated... + */ + +#include <sys/types.h> +#include "libioP.h" +#include <string.h> +#ifdef __STDC__ +#include <stdarg.h> +#else +#include <varargs.h> +#endif + +/* + * Define FLOATING_POINT to get floating point. + */ +#ifndef NO_FLOATING_POINT +#define FLOATING_POINT +#endif + +/* end of configuration stuff */ + + +/* + * Helper "class" for `fprintf to unbuffered': creates a + * temporary buffer. */ + +struct helper_file +{ + struct _IO_FILE_plus _f; + _IO_FILE *_put_stream; +}; + +static int +DEFUN(_IO_helper_overflow, (fp, c), + _IO_FILE *fp AND int c) +{ + _IO_FILE *target = ((struct helper_file*)fp)->_put_stream; + int used = fp->_IO_write_ptr - fp->_IO_write_base; + if (used) + { + _IO_sputn(target, fp->_IO_write_base, used); + fp->_IO_write_ptr -= used; + } + return _IO_putc (c, fp); +} + +static struct _IO_jump_t _IO_helper_jumps = { + 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 +DEFUN(helper_vfprintf, (fp, fmt0, ap), + register _IO_FILE* fp AND char const *fmt0 AND _IO_va_list ap) +{ + char buf[_IO_BUFSIZ]; + struct helper_file helper; + register _IO_FILE *hp = (_IO_FILE*)&helper; + int result, to_flush; + + /* initialize helper */ + helper._put_stream = fp; + hp->_IO_write_base = buf; + hp->_IO_write_ptr = buf; + hp->_IO_write_end = buf+_IO_BUFSIZ; + hp->_IO_file_flags = _IO_MAGIC|_IO_NO_READS; + _IO_JUMPS(hp) = &_IO_helper_jumps; + + /* Now print to helper instead. */ + result = _IO_vfprintf(hp, fmt0, ap); + + /* Now flush anything from the helper to the fp. */ + if ((to_flush = hp->_IO_write_ptr - hp->_IO_write_base) > 0) + { + if (_IO_sputn(fp, hp->_IO_write_base, to_flush) != to_flush) + return EOF; + } + return result; +} + +#ifdef FLOATING_POINT + +#include "floatio.h" +#define BUF (MAXEXP+MAXFRACT+1) /* + decimal point */ +#define DEFPREC 6 +extern double modf __P((double, double*)); + +#else /* no FLOATING_POINT */ + +#define BUF 40 + +#endif /* FLOATING_POINT */ + + +/* + * Macros for converting digits to letters and vice versa + */ +#define to_digit(c) ((c) - '0') +#define is_digit(c) ((unsigned)to_digit(c) <= 9) +#define to_char(n) ((n) + '0') + +/* + * Flags used during conversion. + */ +#define LONGINT 0x01 /* long integer */ +#define LONGDBL 0x02 /* long double; unimplemented */ +#define SHORTINT 0x04 /* short integer */ +#define ALT 0x08 /* alternate form */ +#define LADJUST 0x10 /* left adjustment */ +#define ZEROPAD 0x20 /* zero (as opposed to blank) pad */ +#define HEXPREFIX 0x40 /* add 0x or 0X prefix */ + +int +DEFUN(_IO_vfprintf, (fp, fmt0, ap), + register _IO_FILE* fp AND char const *fmt0 AND _IO_va_list ap) +{ + register const char *fmt; /* format string */ + register int ch; /* character from fmt */ + register int n; /* handy integer (short term usage) */ + register char *cp; /* handy char pointer (short term usage) */ + const char *fmark; /* for remembering a place in fmt */ + register int flags; /* flags as above */ + int ret; /* return value accumulator */ + int width; /* width from format (%8d), or 0 */ + int prec; /* precision from format (%.3d), or -1 */ + char sign; /* sign prefix (' ', '+', '-', or \0) */ +#ifdef FLOATING_POINT + int softsign; /* temporary negative sign for floats */ + double _double; /* double precision arguments %[eEfgG] */ +#ifndef _IO_USE_DTOA + int fpprec; /* `extra' floating precision in [eEfgG] */ +#endif +#endif + unsigned long _ulong; /* integer arguments %[diouxX] */ + enum { OCT, DEC, HEX } base;/* base for [diouxX] conversion */ + int dprec; /* a copy of prec if [diouxX], 0 otherwise */ + int dpad; /* extra 0 padding needed for integers */ + int fieldsz; /* field size expanded by sign, dpad etc */ + /* The initialization of 'size' is to suppress a warning that + 'size' might be used unitialized. It seems gcc can't + quite grok this spaghetti code ... */ + int size = 0; /* size of converted field or string */ + char buf[BUF]; /* space for %c, %[diouxX], %[eEfgG] */ + char ox[2]; /* space for 0x hex-prefix */ + + /* + * BEWARE, these `goto error' on error, and PAD uses `n'. + */ +#define PRINT(ptr, len) \ + do { if (_IO_sputn(fp,ptr, len) != len) goto error; } while (0) +#define PAD_SP(howmany) if (_IO_padn(fp, ' ', howmany) < (howmany)) goto error; +#define PAD_0(howmany) if (_IO_padn(fp, '0', howmany) < (howmany)) goto error; + + /* + * To extend shorts properly, we need both signed and unsigned + * argument extraction methods. + */ +#define SARG() \ + (flags&LONGINT ? va_arg(ap, long) : \ + flags&SHORTINT ? (long)(short)va_arg(ap, int) : \ + (long)va_arg(ap, int)) +#define UARG() \ + (flags&LONGINT ? va_arg(ap, unsigned long) : \ + flags&SHORTINT ? (unsigned long)(unsigned short)va_arg(ap, int) : \ + (unsigned long)va_arg(ap, unsigned int)) + + /* optimise stderr (and other unbuffered Unix files) */ + if (fp->_IO_file_flags & _IO_UNBUFFERED) + return helper_vfprintf(fp, fmt0, ap); + + fmt = fmt0; + ret = 0; + + /* + * Scan the format for conversions (`%' character). + */ + for (;;) { + for (fmark = fmt; (ch = *fmt) != '\0' && ch != '%'; fmt++) + /* void */; + if ((n = fmt - fmark) != 0) { + PRINT(fmark, n); + ret += n; + } + if (ch == '\0') + goto done; + fmt++; /* skip over '%' */ + + flags = 0; + dprec = 0; +#if defined(FLOATING_POINT) && !defined (_IO_USE_DTOA) + fpprec = 0; +#endif + width = 0; + prec = -1; + sign = '\0'; + +rflag: ch = *fmt++; +reswitch: switch (ch) { + case ' ': + /* + * ``If the space and + flags both appear, the space + * flag will be ignored.'' + * -- ANSI X3J11 + */ + if (!sign) + sign = ' '; + goto rflag; + case '#': + flags |= ALT; + goto rflag; + case '*': + /* + * ``A negative field width argument is taken as a + * - flag followed by a positive field width.'' + * -- ANSI X3J11 + * They don't exclude field widths read from args. + */ + if ((width = va_arg(ap, int)) >= 0) + goto rflag; + width = -width; + /* FALLTHROUGH */ + case '-': + flags |= LADJUST; + flags &= ~ZEROPAD; /* '-' disables '0' */ + goto rflag; + case '+': + sign = '+'; + goto rflag; + case '.': + if ((ch = *fmt++) == '*') { + n = va_arg(ap, int); + prec = n < 0 ? -1 : n; + goto rflag; + } + n = 0; + while (is_digit(ch)) { + n = 10 * n + to_digit(ch); + ch = *fmt++; + } + prec = n < 0 ? -1 : n; + goto reswitch; + case '0': + /* + * ``Note that 0 is taken as a flag, not as the + * beginning of a field width.'' + * -- ANSI X3J11 + */ + if (!(flags & LADJUST)) + flags |= ZEROPAD; /* '-' disables '0' */ + goto rflag; + case '1': case '2': case '3': case '4': + case '5': case '6': case '7': case '8': case '9': + n = 0; + do { + n = 10 * n + to_digit(ch); + ch = *fmt++; + } while (is_digit(ch)); + width = n; + goto reswitch; +#ifdef FLOATING_POINT + case 'L': + flags |= LONGDBL; + goto rflag; +#endif + case 'h': + flags |= SHORTINT; + goto rflag; + case 'l': + flags |= LONGINT; + goto rflag; + case 'c': + *(cp = buf) = va_arg(ap, int); + size = 1; + sign = '\0'; + break; + case 'D': + flags |= LONGINT; + /*FALLTHROUGH*/ + case 'd': + case 'i': + _ulong = SARG(); + if ((long)_ulong < 0) { + _ulong = -_ulong; + sign = '-'; + } + base = DEC; + goto number; +#ifdef FLOATING_POINT + case 'e': + case 'E': + case 'f': + case 'F': + case 'g': + case 'G': + _double = va_arg(ap, double); +#ifdef _IO_USE_DTOA + { + int fmt_flags = 0; + int fill = ' '; + if (flags & ALT) + fmt_flags |= _IO_SHOWPOINT; + if (flags & LADJUST) + fmt_flags |= _IO_LEFT; + else if (flags & ZEROPAD) + fmt_flags |= _IO_INTERNAL, fill = '0'; + n = _IO_outfloat(_double, fp, ch, width, + prec < 0 ? DEFPREC : prec, + fmt_flags, sign, fill); + if (n < 0) + goto error; + ret += n; + } + /* CHECK ERROR! */ + continue; +#else + /* + * don't do unrealistic precision; just pad it with + * zeroes later, so buffer size stays rational. + */ + if (prec > MAXFRACT) { + if ((ch != 'g' && ch != 'G') || (flags&ALT)) + fpprec = prec - MAXFRACT; + prec = MAXFRACT; + } else if (prec == -1) + prec = DEFPREC; + /* __cvt_double may have to round up before the + "start" of its buffer, i.e. + ``intf("%.2f", (double)9.999);''; + if the first character is still NUL, it did. + softsign avoids negative 0 if _double < 0 but + no significant digits will be shown. */ + cp = buf; + *cp = '\0'; + size = __cvt_double(_double, prec, flags, &softsign, + ch, cp, buf + sizeof(buf)); + if (softsign) + sign = '-'; + if (*cp == '\0') + cp++; + break; +#endif +#endif /* FLOATING_POINT */ + case 'n': + if (flags & LONGINT) + *va_arg(ap, long *) = ret; + else if (flags & SHORTINT) + *va_arg(ap, short *) = ret; + else + *va_arg(ap, int *) = ret; + continue; /* no output */ + case 'O': + flags |= LONGINT; + /*FALLTHROUGH*/ + case 'o': + _ulong = UARG(); + base = OCT; + goto nosign; + case 'p': + /* + * ``The argument shall be a pointer to void. The + * value of the pointer is converted to a sequence + * of printable characters, in an implementation- + * defined manner.'' + * -- ANSI X3J11 + */ + /* NOSTRICT */ + _ulong = (unsigned long)va_arg(ap, void *); + base = HEX; + flags |= HEXPREFIX; + ch = 'x'; + goto nosign; + case 's': + if ((cp = va_arg(ap, char *)) == NULL) + cp = "(null)"; + if (prec >= 0) { + /* + * can't use strlen; can only look for the + * NUL in the first `prec' characters, and + * strlen() will go further. + */ + char *p = (char*)memchr(cp, 0, prec); + + if (p != NULL) { + size = p - cp; + if (size > prec) + size = prec; + } else + size = prec; + } else + size = strlen(cp); + sign = '\0'; + break; + case 'U': + flags |= LONGINT; + /*FALLTHROUGH*/ + case 'u': + _ulong = UARG(); + base = DEC; + goto nosign; + case 'X': + case 'x': + _ulong = UARG(); + base = HEX; + /* leading 0x/X only if non-zero */ + if (flags & ALT && _ulong != 0) + flags |= HEXPREFIX; + + /* unsigned conversions */ +nosign: sign = '\0'; + /* + * ``... diouXx conversions ... if a precision is + * specified, the 0 flag will be ignored.'' + * -- ANSI X3J11 + */ +number: if ((dprec = prec) >= 0) + flags &= ~ZEROPAD; + + /* + * ``The result of converting a zero value with an + * explicit precision of zero is no characters.'' + * -- ANSI X3J11 + */ + cp = buf + BUF; + if (_ulong != 0 || prec != 0) { + char *xdigs; /* digits for [xX] conversion */ + /* + * unsigned mod is hard, and unsigned mod + * by a constant is easier than that by + * a variable; hence this switch. + */ + switch (base) { + case OCT: + do { + *--cp = to_char(_ulong & 7); + _ulong >>= 3; + } while (_ulong); + /* handle octal leading 0 */ + if (flags & ALT && *cp != '0') + *--cp = '0'; + break; + + case DEC: + /* many numbers are 1 digit */ + while (_ulong >= 10) { + *--cp = to_char(_ulong % 10); + _ulong /= 10; + } + *--cp = to_char(_ulong); + break; + + case HEX: + if (ch == 'X') + xdigs = "0123456789ABCDEF"; + else /* ch == 'x' || ch == 'p' */ + xdigs = "0123456789abcdef"; + do { + *--cp = xdigs[_ulong & 15]; + _ulong >>= 4; + } while (_ulong); + break; + + default: + cp = "bug in vform: bad base"; + goto skipsize; + } + } + size = buf + BUF - cp; + skipsize: + break; + default: /* "%?" prints ?, unless ? is NUL */ + if (ch == '\0') + goto done; + /* pretend it was %c with argument ch */ + cp = buf; + *cp = ch; + size = 1; + sign = '\0'; + break; + } + + /* + * All reasonable formats wind up here. At this point, + * `cp' points to a string which (if not flags&LADJUST) + * should be padded out to `width' places. If + * flags&ZEROPAD, it should first be prefixed by any + * sign or other prefix; otherwise, it should be blank + * padded before the prefix is emitted. After any + * left-hand padding and prefixing, emit zeroes + * required by a decimal [diouxX] precision, then print + * the string proper, then emit zeroes required by any + * leftover floating precision; finally, if LADJUST, + * pad with blanks. + */ + + /* + * compute actual size, so we know how much to pad. + */ +#if defined(FLOATING_POINT) && !defined (_IO_USE_DTOA) + fieldsz = size + fpprec; +#else + fieldsz = size; +#endif + dpad = dprec - size; + if (dpad < 0) + dpad = 0; + + if (sign) + fieldsz++; + else if (flags & HEXPREFIX) + fieldsz += 2; + fieldsz += dpad; + + /* right-adjusting blank padding */ + if ((flags & (LADJUST|ZEROPAD)) == 0) + PAD_SP(width - fieldsz); + + /* prefix */ + if (sign) { + PRINT(&sign, 1); + } else if (flags & HEXPREFIX) { + ox[0] = '0'; + ox[1] = ch; + PRINT(ox, 2); + } + + /* right-adjusting zero padding */ + if ((flags & (LADJUST|ZEROPAD)) == ZEROPAD) + PAD_0(width - fieldsz); + + /* leading zeroes from decimal precision */ + PAD_0(dpad); + + /* the string or number proper */ + PRINT(cp, size); + +#if defined(FLOATING_POINT) && !defined (_IO_USE_DTOA) + /* trailing f.p. zeroes */ + PAD_0(fpprec); +#endif + + /* left-adjusting padding (always blank) */ + if (flags & LADJUST) + PAD_SP(width - fieldsz); + + /* finally, adjust ret */ + ret += width > fieldsz ? width : fieldsz; + + } +done: + return ret; +error: + return EOF; + /* NOTREACHED */ +} + +#if defined(FLOATING_POINT) && !defined(_IO_USE_DTOA) + +static char *exponent(register char *p, register int exp, int fmtch) +{ + register char *t; + char expbuf[MAXEXP]; + + *p++ = fmtch; + if (exp < 0) { + exp = -exp; + *p++ = '-'; + } + else + *p++ = '+'; + t = expbuf + MAXEXP; + if (exp > 9) { + do { + *--t = to_char(exp % 10); + } while ((exp /= 10) > 9); + *--t = to_char(exp); + for (; t < expbuf + MAXEXP; *p++ = *t++); + } + else { + *p++ = '0'; + *p++ = to_char(exp); + } + return (p); +} + +static char * round(double fract, int *exp, + register char *start, register char *end, + char ch, int *signp) +{ + double tmp; + + if (fract) + (void)modf(fract * 10, &tmp); + else + tmp = to_digit(ch); + if (tmp > 4) + for (;; --end) { + if (*end == '.') + --end; + if (++*end <= '9') + break; + *end = '0'; + if (end == start) { + if (exp) { /* e/E; increment exponent */ + *end = '1'; + ++*exp; + } + else { /* f; add extra digit */ + *--end = '1'; + --start; + } + break; + } + } + /* ``"%.3f", (double)-0.0004'' gives you a negative 0. */ + else if (*signp == '-') + for (;; --end) { + if (*end == '.') + --end; + if (*end != '0') + break; + if (end == start) + *signp = 0; + } + return (start); +} + +int __cvt_double(double number, register int prec, int flags, int *signp, + int fmtch, char *startp, char *endp) +{ + register char *p, *t; + register double fract; + int dotrim = 0, expcnt, gformat = 0; + double integer, tmp; + + expcnt = 0; + if (number < 0) { + number = -number; + *signp = '-'; + } else + *signp = 0; + + fract = modf(number, &integer); + + /* get an extra slot for rounding. */ + t = ++startp; + + /* + * get integer portion of number; put into the end of the buffer; the + * .01 is added for modf(356.0 / 10, &integer) returning .59999999... + */ + for (p = endp - 1; integer; ++expcnt) { + tmp = modf(integer / 10, &integer); + *p-- = to_char((int)((tmp + .01) * 10)); + } + switch (fmtch) { + case 'f': + case 'F': + /* reverse integer into beginning of buffer */ + if (expcnt) + for (; ++p < endp; *t++ = *p); + else + *t++ = '0'; + /* + * if precision required or alternate flag set, add in a + * decimal point. + */ + if (prec || flags&ALT) + *t++ = '.'; + /* if requires more precision and some fraction left */ + if (fract) { + if (prec) + do { + fract = modf(fract * 10, &tmp); + *t++ = to_char((int)tmp); + } while (--prec && fract); + if (fract) + startp = round(fract, (int *)NULL, startp, + t - 1, (char)0, signp); + } + for (; prec--; *t++ = '0'); + break; + case 'e': + case 'E': +eformat: if (expcnt) { + *t++ = *++p; + if (prec || flags&ALT) + *t++ = '.'; + /* if requires more precision and some integer left */ + for (; prec && ++p < endp; --prec) + *t++ = *p; + /* + * if done precision and more of the integer component, + * round using it; adjust fract so we don't re-round + * later. + */ + if (!prec && ++p < endp) { + fract = 0; + startp = round((double)0, &expcnt, startp, + t - 1, *p, signp); + } + /* adjust expcnt for digit in front of decimal */ + --expcnt; + } + /* until first fractional digit, decrement exponent */ + else if (fract) { + /* adjust expcnt for digit in front of decimal */ + for (expcnt = -1;; --expcnt) { + fract = modf(fract * 10, &tmp); + if (tmp) + break; + } + *t++ = to_char((int)tmp); + if (prec || flags&ALT) + *t++ = '.'; + } + else { + *t++ = '0'; + if (prec || flags&ALT) + *t++ = '.'; + } + /* if requires more precision and some fraction left */ + if (fract) { + if (prec) + do { + fract = modf(fract * 10, &tmp); + *t++ = to_char((int)tmp); + } while (--prec && fract); + if (fract) + startp = round(fract, &expcnt, startp, + t - 1, (char)0, signp); + } + /* if requires more precision */ + for (; prec--; *t++ = '0'); + + /* unless alternate flag, trim any g/G format trailing 0's */ + if (gformat && !(flags&ALT)) { + while (t > startp && *--t == '0'); + if (*t == '.') + --t; + ++t; + } + t = exponent(t, expcnt, fmtch); + break; + case 'g': + case 'G': + /* a precision of 0 is treated as a precision of 1. */ + if (!prec) + ++prec; + /* + * ``The style used depends on the value converted; style e + * will be used only if the exponent resulting from the + * conversion is less than -4 or greater than the precision.'' + * -- ANSI X3J11 + */ + if (expcnt > prec || (!expcnt && fract && fract < .0001)) { + /* + * g/G format counts "significant digits, not digits of + * precision; for the e/E format, this just causes an + * off-by-one problem, i.e. g/G considers the digit + * before the decimal point significant and e/E doesn't + * count it as precision. + */ + --prec; + fmtch -= 2; /* G->E, g->e */ + gformat = 1; + goto eformat; + } + /* + * reverse integer into beginning of buffer, + * note, decrement precision + */ + if (expcnt) + for (; ++p < endp; *t++ = *p, --prec); + else + *t++ = '0'; + /* + * if precision required or alternate flag set, add in a + * decimal point. If no digits yet, add in leading 0. + */ + if (prec || flags&ALT) { + dotrim = 1; + *t++ = '.'; + } + else + dotrim = 0; + /* if requires more precision and some fraction left */ + if (fract) { + if (prec) { + /* If no integer part, don't count initial + * zeros as significant digits. */ + do { + fract = modf(fract * 10, &tmp); + *t++ = to_char((int)tmp); + } while(!tmp && !expcnt); + while (--prec && fract) { + fract = modf(fract * 10, &tmp); + *t++ = to_char((int)tmp); + } + } + if (fract) + startp = round(fract, (int *)NULL, startp, + t - 1, (char)0, signp); + } + /* alternate format, adds 0's for precision, else trim 0's */ + if (flags&ALT) + for (; prec--; *t++ = '0'); + else if (dotrim) { + while (t > startp && *--t == '0'); + if (*t != '.') + ++t; + } + } + return (t - startp); +} + +#endif /* defined(FLOATING_POINT) && !defined(_IO_USE_DTOA) */ diff --git a/gnu/lib/libg++/libio/iovfscanf.c b/gnu/lib/libg++/libio/iovfscanf.c new file mode 100644 index 00000000000..1220e0750b7 --- /dev/null +++ b/gnu/lib/libg++/libio/iovfscanf.c @@ -0,0 +1,787 @@ +/* +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. + */ + +/* Extensively hacked for GNU iostream by Per Bothner 1991, 1992, 1993. + Changes copyright Free Software Foundation 1992, 1993. */ + +#if defined(LIBC_SCCS) && !defined(lint) +static char sccsid[] = "%W% (Berkeley) %G%"; +#endif /* LIBC_SCCS and not lint */ + +#include <libioP.h> +#include <ctype.h> +#ifdef __STDC__ +#include <stdarg.h> +#else +#include <varargs.h> +#endif + +#ifndef NO_FLOATING_POINT +#define FLOATING_POINT +#endif + +#ifdef FLOATING_POINT +#include "floatio.h" +#define BUF (MAXEXP+MAXFRACT+3) /* 3 = sign + decimal point + NUL */ +#else +#define BUF 40 +#endif + +/* + * Flags used during conversion. + */ +#define LONG 0x01 /* l: long or double */ +#define LONGDBL 0x02 /* L: long double; unimplemented */ +#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 */ + +/* + * The following are used in numeric conversions only: + * SIGNOK, NDIGITS, DPTOK, and EXPOK are for floating point; + * SIGNOK, NDIGITS, PFXOK, and NZDIGITS are for integral. + */ +#define SIGNOK 0x40 /* +/- is (still) legal */ +#define NDIGITS 0x80 /* no digits detected */ + +#define DPTOK 0x100 /* (float) decimal point is still legal */ +#define EXPOK 0x200 /* (float) exponent (e+3, etc) still legal */ + +#define PFXOK 0x100 /* 0x prefix is (still) legal */ +#define NZDIGITS 0x200 /* no zero digits detected */ + +/* + * Conversion types. + */ +#define CT_CHAR 0 /* %c conversion */ +#define CT_CCL 1 /* %[...] conversion */ +#define CT_STRING 2 /* %s conversion */ +#define CT_INT 3 /* integer, i.e., strtol or strtoul */ +#define CT_FLOAT 4 /* floating, i.e., strtod */ + +#define u_char unsigned char +#define u_long unsigned long + +#ifdef __cplusplus +extern "C" { +#endif +extern u_long strtoul __P((const char*, char**, int)); +extern long strtol __P((const char*, char**, int)); +static const u_char *__sccl __P((char *tab, const u_char *fmt)); +#ifndef _IO_USE_DTOA +extern double atof(); +#endif +#ifdef __cplusplus +} +#endif + +/* If errp != NULL, *errp|=1 if we see a premature EOF; + *errp|=2 if we an invalid character. */ + +int +DEFUN(_IO_vfscanf, (fp, fmt0, ap, errp), + register _IO_FILE *fp AND char const *fmt0 + AND _IO_va_list ap AND int *errp) +{ + register const u_char *fmt = (const u_char *)fmt0; + register int c; /* character from format, or conversion */ + register _IO_ssize_t width; /* field width, or 0 */ + register char *p; /* points into all kinds of strings */ + register int n; /* handy integer */ + register int flags = 0; /* flags as defined above */ + register char *p0; /* saves original value of p when necessary */ + int nassigned; /* number of fields assigned */ + int nread; /* number of characters consumed from fp */ + /* Assignments to base and ccfn are just to suppress warnings from gcc.*/ + int base = 0; /* base argument to strtol/strtoul */ + typedef u_long (*strtoulfn) __P((const char*, char**, int)); + strtoulfn ccfn = 0; + /* conversion function (strtol/strtoul) */ + char ccltab[256]; /* character class table for %[...] */ + char buf[BUF]; /* buffer for numeric conversions */ + int seen_eof = 0; + + /* `basefix' is used to avoid `if' tests in the integer scanner */ + static short basefix[17] = + { 10, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16 }; + + nassigned = 0; + nread = 0; + for (;;) { + c = *fmt++; + if (c == 0) + goto done; + if (isspace(c)) { + for (;;) { + c = _IO_getc(fp); + if (c == EOF) { + seen_eof++; + break; + } + if (!isspace(c)) { + _IO_ungetc (c, fp); + break; + } + nread++; + } + continue; + } + if (c != '%') + goto literal; + width = 0; + flags = 0; + /* + * switch on the format. continue if done; + * break once format type is derived. + */ +again: c = *fmt++; + switch (c) { + case '%': +literal: + n = _IO_getc(fp); + if (n == EOF) + goto eof_failure; + if (n != c) { + _IO_ungetc (n, fp); + goto match_failure; + } + nread++; + continue; + + case '*': + if (flags) goto control_failure; + flags = SUPPRESS; + goto again; + case 'l': + if (flags & ~(SUPPRESS | WIDTH)) goto control_failure; + flags |= LONG; + goto again; + case 'L': + if (flags & ~(SUPPRESS | WIDTH)) goto control_failure; + flags |= LONGDBL; + goto again; + case 'h': + if (flags & ~(SUPPRESS | WIDTH)) goto control_failure; + flags |= SHORT; + goto again; + + case '0': case '1': case '2': case '3': case '4': + case '5': case '6': case '7': case '8': case '9': + if (flags & ~(SUPPRESS | WIDTH)) goto control_failure; + flags |= WIDTH; + width = width * 10 + c - '0'; + goto again; + + /* + * Conversions. + * Those marked `compat' are for 4.[123]BSD compatibility. + * + * (According to ANSI, E and X formats are supposed + * to the same as e and x. Sorry about that.) + */ + case 'D': /* compat */ + flags |= LONG; + /* FALLTHROUGH */ + case 'd': + c = CT_INT; + ccfn = (strtoulfn)strtol; + base = 10; + break; + + case 'i': + c = CT_INT; + ccfn = (strtoulfn)strtol; + base = 0; + break; + + case 'O': /* compat */ + flags |= LONG; + /* FALLTHROUGH */ + case 'o': + c = CT_INT; + ccfn = strtoul; + base = 8; + break; + + case 'u': + c = CT_INT; + ccfn = strtoul; + base = 10; + break; + + case 'X': + case 'x': + flags |= PFXOK; /* enable 0x prefixing */ + c = CT_INT; + ccfn = strtoul; + base = 16; + break; + +#ifdef FLOATING_POINT + case 'E': case 'F': + case 'e': case 'f': case 'g': + c = CT_FLOAT; + break; +#endif + + case 's': + c = CT_STRING; + break; + + case '[': + fmt = __sccl(ccltab, fmt); + flags |= NOSKIP; + c = CT_CCL; + break; + + case 'c': + flags |= NOSKIP; + c = CT_CHAR; + break; + + case 'p': /* pointer format is like hex */ + flags |= POINTER | PFXOK; + c = CT_INT; + ccfn = strtoul; + base = 16; + break; + + case 'n': + if (flags & SUPPRESS) /* ??? */ + continue; + if (flags & SHORT) + *va_arg(ap, short *) = nread; + else if (flags & LONG) + *va_arg(ap, long *) = nread; + else + *va_arg(ap, int *) = nread; + continue; + + /* + * Disgusting backwards compatibility hacks. XXX + */ + case '\0': /* compat */ + nassigned = EOF; + goto done; + + default: /* compat */ + if (isupper(c)) + flags |= LONG; + c = CT_INT; + ccfn = (strtoulfn)strtol; + base = 10; + break; + } + + /* + * We have a conversion that requires input. + */ + if (_IO_peekc(fp) == EOF) + goto eof_failure; + + /* + * Consume leading white space, except for formats + * that suppress this. + */ + if ((flags & NOSKIP) == 0) { + n = (unsigned char)*fp->_IO_read_ptr; + while (isspace(n)) { + fp->_IO_read_ptr++; + nread++; + n = _IO_peekc(fp); + if (n == EOF) + goto eof_failure; + } + /* Note that there is at least one character in + the buffer, so conversions that do not set NOSKIP + can no longer result in an input failure. */ + } + + /* + * Do the conversion. + */ + switch (c) { + + case CT_CHAR: + /* scan arbitrary characters (sets NOSKIP) */ + if (width == 0) /* FIXME! */ + width = 1; + if (flags & SUPPRESS) { + _IO_size_t sum = 0; + for (;;) { + n = fp->_IO_read_end - fp->_IO_read_ptr; + if (n < (int)width) { + sum += n; + width -= n; + fp->_IO_read_ptr += n; + if (__underflow(fp) == EOF) + if (sum == 0) + goto eof_failure; + else { + seen_eof++; + break; + } + } else { + sum += width; + fp->_IO_read_ptr += width; + break; + } + } + nread += sum; + } else { + _IO_size_t r = + + _IO_XSGETN (fp, (char*)va_arg(ap, char*), width); + if (r != width) + goto eof_failure; + nread += r; + nassigned++; + } + break; + + case CT_CCL: + /* scan a (nonempty) character class (sets NOSKIP) */ + if (width == 0) + width = ~0; /* `infinity' */ + /* take only those things in the class */ + if (flags & SUPPRESS) { + n = 0; + while (ccltab[(unsigned char)*fp->_IO_read_ptr]) { + n++, fp->_IO_read_ptr++; + if (--width == 0) + break; + if (_IO_peekc(fp) == EOF) { + if (n == 0) + goto eof_failure; + seen_eof++; + break; + } + } + if (n == 0) + goto match_failure; + } else { + p0 = p = va_arg(ap, char *); + while (ccltab[(unsigned char)*fp->_IO_read_ptr]) { + *p++ = *fp->_IO_read_ptr++; + if (--width == 0) + break; + if (_IO_peekc(fp) == EOF) { + if (p == p0) + goto eof_failure; + seen_eof++; + break; + } + } + n = p - p0; + if (n == 0) + goto match_failure; + *p = 0; + nassigned++; + } + nread += n; + break; + + case CT_STRING: + /* like CCL, but zero-length string OK, & no NOSKIP */ + if (width == 0) + width = ~0; + if (flags & SUPPRESS) { + n = 0; + while (!isspace((unsigned char)*fp->_IO_read_ptr)) { + n++, fp->_IO_read_ptr++; + if (--width == 0) + break; + if (_IO_peekc(fp) == EOF) { + seen_eof++; + break; + } + } + nread += n; + } else { + p0 = p = va_arg(ap, char *); + while (!isspace((unsigned char)*fp->_IO_read_ptr)) { + *p++ = *fp->_IO_read_ptr++; + if (--width == 0) + break; + if (_IO_peekc(fp) == EOF) { + seen_eof++; + break; + } + } + *p = 0; + nread += p - p0; + nassigned++; + } + continue; + + case CT_INT: + /* scan an integer as if by strtol/strtoul */ + if (width == 0 || width > sizeof(buf) - 1) + width = sizeof(buf) - 1; + flags |= SIGNOK | NDIGITS | NZDIGITS; + for (p = buf; width; width--) { + c = (unsigned char)*fp->_IO_read_ptr; + /* + * Switch on the character; `goto ok' + * if we accept it as a part of number. + */ + switch (c) { + + /* + * The digit 0 is always legal, but is + * special. For %i conversions, if no + * digits (zero or nonzero) have been + * scanned (only signs), we will have + * base==0. In that case, we should set + * it to 8 and enable 0x prefixing. + * Also, if we have not scanned zero digits + * before this, do not turn off prefixing + * (someone else will turn it off if we + * have scanned any nonzero digits). + */ + case '0': + if (base == 0) { + base = 8; + flags |= PFXOK; + } + if (flags & NZDIGITS) + flags &= ~(SIGNOK|NZDIGITS|NDIGITS); + else + flags &= ~(SIGNOK|PFXOK|NDIGITS); + goto ok; + + /* 1 through 7 always legal */ + case '1': case '2': case '3': + case '4': case '5': case '6': case '7': + base = basefix[base]; + flags &= ~(SIGNOK | PFXOK | NDIGITS); + goto ok; + + /* digits 8 and 9 ok iff decimal or hex */ + case '8': case '9': + base = basefix[base]; + if (base <= 8) + break; /* not legal here */ + flags &= ~(SIGNOK | PFXOK | NDIGITS); + goto ok; + + /* letters ok iff hex */ + case 'A': case 'B': case 'C': + case 'D': case 'E': case 'F': + case 'a': case 'b': case 'c': + case 'd': case 'e': case 'f': + /* no need to fix base here */ + if (base <= 10) + break; /* not legal here */ + flags &= ~(SIGNOK | PFXOK | NDIGITS); + goto ok; + + /* sign ok only as first character */ + case '+': case '-': + if (flags & SIGNOK) { + flags &= ~SIGNOK; + goto ok; + } + break; + + /* x ok iff flag still set & 2nd char */ + case 'x': case 'X': + if (flags & PFXOK && p == buf + 1) { + base = 16; /* if %i */ + flags &= ~PFXOK; + goto ok; + } + break; + } + + /* + * If we got here, c is not a legal character + * for a number. Stop accumulating digits. + */ + break; + ok: + /* + * c is legal: store it and look at the next. + */ + *p++ = c; + fp->_IO_read_ptr++; + if (_IO_peekc(fp) == EOF) { + seen_eof++; + break; /* EOF */ + } + } + /* + * If we had only a sign, it is no good; push + * back the sign. If the number ends in `x', + * it was [sign] '0' 'x', so push back the x + * and treat it as [sign] '0'. + */ + if (flags & NDIGITS) { + if (p > buf) + (void) _IO_ungetc(*(u_char *)--p, fp); + goto match_failure; + } + c = ((u_char *)p)[-1]; + if (c == 'x' || c == 'X') { + --p; + (void) _IO_ungetc (c, fp); + } + if ((flags & SUPPRESS) == 0) { + u_long res; + + *p = 0; + res = (*ccfn)(buf, (char **)NULL, base); + if (flags & POINTER) + *va_arg(ap, void **) = (void *)res; + else if (flags & SHORT) + *va_arg(ap, short *) = res; + else if (flags & LONG) + *va_arg(ap, long *) = res; + else + *va_arg(ap, int *) = res; + nassigned++; + } + nread += p - buf; + break; + +#ifdef FLOATING_POINT + case CT_FLOAT: + /* scan a floating point number as if by strtod */ + if (width == 0 || width > sizeof(buf) - 1) + width = sizeof(buf) - 1; + flags |= SIGNOK | NDIGITS | DPTOK | EXPOK; + for (p = buf; width; width--) { + c = (unsigned char)*fp->_IO_read_ptr; + /* + * This code mimicks the integer conversion + * code, but is much simpler. + */ + switch (c) { + + case '0': case '1': case '2': case '3': + case '4': case '5': case '6': case '7': + case '8': case '9': + flags &= ~(SIGNOK | NDIGITS); + goto fok; + + case '+': case '-': + if (flags & SIGNOK) { + flags &= ~SIGNOK; + goto fok; + } + break; + case '.': + if (flags & DPTOK) { + flags &= ~(SIGNOK | DPTOK); + goto fok; + } + break; + case 'e': case 'E': + /* no exponent without some digits */ + if ((flags&(NDIGITS|EXPOK)) == EXPOK) { + flags = + (flags & ~(EXPOK|DPTOK)) | + SIGNOK | NDIGITS; + goto fok; + } + break; + } + break; + fok: + *p++ = c; + fp->_IO_read_ptr++; + if (_IO_peekc(fp) == EOF) { + seen_eof++; + break; /* EOF */ + } + } + /* + * If no digits, might be missing exponent digits + * (just give back the exponent) or might be missing + * regular digits, but had sign and/or decimal point. + */ + if (flags & NDIGITS) { + if (flags & EXPOK) { + /* no digits at all */ + while (p > buf) + _IO_ungetc (*(u_char *)--p, fp); + goto match_failure; + } + /* just a bad exponent (e and maybe sign) */ + c = *(u_char *)--p; + if (c != 'e' && c != 'E') { + (void) _IO_ungetc (c, fp);/* sign */ + c = *(u_char *)--p; + } + (void) _IO_ungetc (c, fp); + } + if ((flags & SUPPRESS) == 0) { + double res; + *p = 0; +#ifdef _IO_USE_DTOA + res = _IO_strtod(buf, NULL); +#else + res = atof(buf); +#endif + if (flags & LONG) + *va_arg(ap, double *) = res; + else + *va_arg(ap, float *) = res; + nassigned++; + } + nread += p - buf; + break; +#endif /* FLOATING_POINT */ + } + } +eof_failure: + seen_eof++; +input_failure: + if (nassigned == 0) + nassigned = -1; +control_failure: +match_failure: + if (errp) + *errp |= 2; +done: + if (errp && seen_eof) + *errp |= 1; + return (nassigned); +} + +/* + * Fill in the given table from the scanset at the given format + * (just after `['). Return a pointer to the character past the + * closing `]'. The table has a 1 wherever characters should be + * considered part of the scanset. + */ +static const u_char * +DEFUN(__sccl, (tab, fmt), + register char *tab AND register const u_char *fmt) +{ + register int c, n, v; + + /* first `clear' the whole table */ + c = *fmt++; /* first char hat => negated scanset */ + if (c == '^') { + v = 1; /* default => accept */ + c = *fmt++; /* get new first char */ + } else + v = 0; /* default => reject */ + /* should probably use memset here */ + for (n = 0; n < 256; n++) + tab[n] = v; + if (c == 0) + return (fmt - 1);/* format ended before closing ] */ + + /* + * Now set the entries corresponding to the actual scanset + * to the opposite of the above. + * + * The first character may be ']' (or '-') without being special; + * the last character may be '-'. + */ + v = 1 - v; + for (;;) { + tab[c] = v; /* take character c */ +doswitch: + n = *fmt++; /* and examine the next */ + switch (n) { + + case 0: /* format ended too soon */ + return (fmt - 1); + + case '-': + /* + * A scanset of the form + * [01+-] + * is defined as `the digit 0, the digit 1, + * the character +, the character -', but + * the effect of a scanset such as + * [a-zA-Z0-9] + * is implementation defined. The V7 Unix + * scanf treats `a-z' as `the letters a through + * z', but treats `a-a' as `the letter a, the + * character -, and the letter a'. + * + * For compatibility, the `-' is not considerd + * to define a range if the character following + * it is either a close bracket (required by ANSI) + * or is not numerically greater than the character + * we just stored in the table (c). + */ + n = *fmt; + if (n == ']' || n < c) { + c = '-'; + break; /* resume the for(;;) */ + } + fmt++; + do { /* fill in the range */ + tab[++c] = v; + } while (c < n); +#if 1 /* XXX another disgusting compatibility hack */ + /* + * Alas, the V7 Unix scanf also treats formats + * such as [a-c-e] as `the letters a through e'. + * This too is permitted by the standard.... + */ + goto doswitch; +#else + c = *fmt++; + if (c == 0) + return (fmt - 1); + if (c == ']') + return (fmt); +#endif + break; + + case ']': /* end of scanset */ + return (fmt); + + default: /* just another character */ + c = n; + break; + } + } + /* NOTREACHED */ +} diff --git a/gnu/lib/libg++/libio/iovsprintf.c b/gnu/lib/libg++/libio/iovsprintf.c new file mode 100644 index 00000000000..06d926d3590 --- /dev/null +++ b/gnu/lib/libg++/libio/iovsprintf.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 "strfile.h" + +int +DEFUN(_IO_vsprintf, (string, format, args), + char *string AND const char *format AND _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; +} diff --git a/gnu/lib/libg++/libio/iovsscanf.c b/gnu/lib/libg++/libio/iovsscanf.c new file mode 100644 index 00000000000..529778098a5 --- /dev/null +++ b/gnu/lib/libg++/libio/iovsscanf.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 "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); +} diff --git a/gnu/lib/libg++/libio/isgetline.cc b/gnu/lib/libg++/libio/isgetline.cc new file mode 100644 index 00000000000..add26638b20 --- /dev/null +++ b/gnu/lib/libg++/libio/isgetline.cc @@ -0,0 +1,139 @@ +/* This is part of libio/iostream, providing -*- C++ -*- input/output. +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 "iostream.h" +#include <string.h> + +istream& istream::getline(char* buf, int len, char delim) +{ + _gcount = 0; + if (len <= 0) + { + set(ios::failbit); + return *this; + } + int ch; + if (ipfx1()) + { + streambuf *sb = rdbuf(); + _gcount = _IO_getline(sb, buf, len - 1, delim, -1); + ch = sb->sbumpc(); + if (ch == EOF) + set (_gcount == 0 ? (ios::failbit|ios::eofbit) : ios::eofbit); + else if (ch != (unsigned char) delim) + { + set(ios::failbit); + sb->sungetc(); // Leave delimiter unread. + } + } + else + ch = EOF; + buf[_gcount] = '\0'; + if (ch == (unsigned char)delim) + _gcount++; // The delimiter is counted in the gcount(). + return *this; +} + +istream& istream::get(char* buf, int len, char delim) +{ + _gcount = 0; + if (len <= 0) + { + set(ios::failbit); + return *this; + } + if (ipfx1()) + { + streambuf *sbuf = rdbuf(); + long count = _IO_getline(sbuf, buf, len - 1, delim, -1); + if (count == 0 && sbuf->sgetc() == EOF) + set(ios::failbit|ios::eofbit); + else + _gcount = count; + } + buf[_gcount] = '\0'; + return *this; +} + + +// from Doug Schmidt + +#define CHUNK_SIZE 512 + +/* Reads an arbitrarily long input line terminated by a user-specified + TERMINATOR. Super-nifty trick using recursion avoids unnecessary calls + to NEW! */ + +char *_sb_readline (streambuf *sb, long& total, char terminator) +{ + char buf[CHUNK_SIZE]; + char *ptr; + int ch; + + _IO_size_t count = _IO_getline(sb, buf, CHUNK_SIZE, terminator, -1); + ch = sb->sbumpc(); + long old_total = total; + total += count; + if (ch != EOF && ch != terminator) { + total++; // Include ch in total. + ptr = _sb_readline(sb, total, terminator); + if (ptr) { + memcpy(ptr + old_total, buf, count); + ptr[old_total+count] = ch; + } + return ptr; + } + + ptr = new char[total+1]; + if (ptr != NULL) { + ptr[total] = '\0'; + memcpy(ptr + total - count, buf, count); + } + return ptr; +} + +/* Reads an arbitrarily long input line terminated by TERMINATOR. + This routine allocates its own memory, so the user should + only supply the address of a (char *). */ + +istream& istream::gets(char **s, char delim /* = '\n' */) +{ + if (ipfx1()) { + long size = 0; + streambuf *sb = rdbuf(); + *s = _sb_readline (sb, size, delim); + _gcount = *s ? size : 0; + if (sb->_flags & _IO_EOF_SEEN) { + set(ios::eofbit); + if (_gcount == 0) + set(ios::failbit); + } + } + else { + _gcount = 0; + *s = NULL; + } + return *this; +} diff --git a/gnu/lib/libg++/libio/isgetsb.cc b/gnu/lib/libg++/libio/isgetsb.cc new file mode 100644 index 00000000000..55617e649a0 --- /dev/null +++ b/gnu/lib/libg++/libio/isgetsb.cc @@ -0,0 +1,59 @@ +/* This is part of libio/iostream, providing -*- C++ -*- input/output. +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 "iostream.h" +#include <string.h> + +istream& istream::get(streambuf& sb, char delim /* = '\n' */) +{ + _gcount = 0; + if (ipfx1()) + { + register streambuf* isb = rdbuf(); + for (;;) + { + streamsize len = isb->_IO_read_end - isb->_IO_read_ptr; + if (len <= 0) + if (__underflow(isb) == EOF) + break; + else + len = isb->_IO_read_end - isb->_IO_read_ptr; + char *delimp = (char*)memchr((void*)isb->_IO_read_ptr, delim, len); + if (delimp != NULL) + len = delimp - isb->_IO_read_ptr; + int written = sb.sputn(isb->_IO_read_ptr, len); + isb->_IO_read_ptr += written; + _gcount += written; + if (written != len) + { + set(ios::failbit); + break; + } + if (delimp != NULL) + break; + } + } + return *this; +} diff --git a/gnu/lib/libg++/libio/isscan.cc b/gnu/lib/libg++/libio/isscan.cc new file mode 100644 index 00000000000..64d4bc682f8 --- /dev/null +++ b/gnu/lib/libg++/libio/isscan.cc @@ -0,0 +1,45 @@ +/* +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 <iostream.h> +#include <stdarg.h> + +istream& istream::scan(const char *format ...) +{ + if (ipfx0()) { + va_list ap; + va_start(ap, format); + _strbuf->vscan(format, ap, this); + va_end(ap); + } + return *this; +} + +istream& istream::vscan(const char *format, _IO_va_list args) +{ + if (ipfx0()) + _strbuf->vscan(format, args, this); + return *this; +} diff --git a/gnu/lib/libg++/libio/istream.h b/gnu/lib/libg++/libio/istream.h new file mode 100644 index 00000000000..f54ec1de9a1 --- /dev/null +++ b/gnu/lib/libg++/libio/istream.h @@ -0,0 +1,25 @@ +/* +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 <stream.h> diff --git a/gnu/lib/libg++/libio/libio.h b/gnu/lib/libg++/libio/libio.h new file mode 100644 index 00000000000..7080d1359d7 --- /dev/null +++ b/gnu/lib/libg++/libio/libio.h @@ -0,0 +1,254 @@ +/* +Copyright (C) 1991, 1992, 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 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 +#if _G_HAVE_SYS_CDEFS +#include <sys/cdefs.h> +#else +#ifdef __STDC__ +#define __P(protos) protos +#else +#define __P(protos) () +#endif +#endif +#endif /*!__P*/ + +/* For backward compatibility */ +#ifndef _PARAMS +#define _PARAMS(protos) __P(protos) +#endif /*!_PARAMS*/ + +#ifndef __STDC__ +#define const +#endif +#define _IO_USE_DTOA +#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 + +/* A streammarker remembers a position in a buffer. */ + +struct _IO_jump_t; struct _IO_FILE; + +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; + + 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; */ +}; + +#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 _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 void _IO_free_backup_area __P((_IO_FILE*)); + +#ifdef __cplusplus +} +#endif + +#endif /* _IO_STDIO_H */ diff --git a/gnu/lib/libg++/libio/libioP.h b/gnu/lib/libg++/libio/libioP.h new file mode 100644 index 00000000000..1b32a59de64 --- /dev/null +++ b/gnu/lib/libg++/libio/libioP.h @@ -0,0 +1,481 @@ +/* +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 + +/* THE JUMPTABLE FUNCTIONS. + + * The _IO_FILE type is used to implement the FILE type in GNU libc, + * as well as the streambuf class in GNU iostreams for C++. + * These are all the same, just used differently. + * An _IO_FILE (or FILE) object is allows followed by a pointer to + * a jump table (of pointers to functions). The pointer is accessed + * with the _IO_JUMPS macro. The jump table has a eccentric format, + * so as to be compatible with the layout of a C++ virtual function table. + * (as implemented by g++). When a pointer to a steambuf object is + * coerced to an (_IO_FILE*), then _IO_JUMPS on the result just + * happens to point to the virtual function table of the streambuf. + * Thus the _IO_JUMPS function table used for C stdio/libio does + * double duty as the virtual functiuon table for C++ streambuf. + * + * The entries in the _IO_JUMPS function table (and hence also the + * virtual functions of a streambuf) are described below. + * The first parameter of each function entry is the _IO_FILE/streambuf + * object being acted on (i.e. the 'this' parameter). + */ + +#define _IO_JUMPS(THIS) ((struct _IO_FILE_plus*)(THIS))->vtable +/* These macros will change when we re-implement vtables to use "thunks"! */ +#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} +#define JUMP_INIT_DUMMY JUMP_INIT(dummy, 0) + +/* The 'finish' function does any final cleaning up of an _IO_FILE object. + It does not delete (free) it, but does everything else to finalize it/ + It matches the streambuf::~streambuf virtual destructor. */ +typedef void (*_IO_finish_t) __P((_IO_FILE*)); /* finalize */ +#define _IO_FINISH(FP) JUMP0(__finish, FP) + +/* The 'overflow' hook flushes the buffer. + The second argument is a character, or EOF. + It matches the streambuf::overflow virtual function. */ +typedef int (*_IO_overflow_t) __P((_IO_FILE*, int)); +#define _IO_OVERFLOW(FP, CH) JUMP1(__overflow, FP, CH) + +/* The 'underflow' hook tries to fills the get buffer. + It returns the next character (as an unsigned char) or EOF. The next + character remains in the get buffer, and the get postion is not changed. + It matches the streambuf::underflow virtual function. */ +typedef int (*_IO_underflow_t) __P((_IO_FILE*)); +#define _IO_UNDERFLOW(FP) JUMP0(__underflow, FP) + +/* The 'uflow' hook returns the next character in the input stream + (cast to unsigned char), and increments the read position; + EOF is returned on failure. + It matches the streambuf::uflow virtual function, which is not in the + cfront implementation, but was added to C++ by the ANSI/ISO committee. */ +#define _IO_UFLOW(FP) JUMP0(__uflow, FP) + +/* The 'pbackfail' hook handles backing up. + It matches the streambuf::pbackfail virtual function. */ +typedef int (*_IO_pbackfail_t) __P((_IO_FILE*, int)); +#define _IO_PBACKFAIL(FP, CH) JUMP1(__pbackfail, FP, CH) + +/* The 'xsputn' hook writes upto N characters from buffer DATA. + Returns the number of character actually written. + It matches the streambuf::xsputn virtual function. */ +typedef _IO_size_t (*_IO_xsputn_t) + __P((_IO_FILE *FP, const void *DATA, _IO_size_t N)); +#define _IO_XSPUTN(FP, DATA, N) JUMP2(__xsputn, FP, DATA, N) + +/* The 'xsgetn' hook reads upto N characters into buffer DATA. + Returns the number of character actually read. + It matches the streambuf::xsgetn virtual function. */ +typedef _IO_size_t (*_IO_xsgetn_t) __P((_IO_FILE*FP, void*DATA, _IO_size_t N)); +#define _IO_XSGETN(FP, DATA, N) JUMP2(__xsgetn, FP, DATA, N) + +/* The 'seekoff' hook moves the stream position to a new position + relative to the start of the file (if DIR==0), the current position + (MODE==1), or the end of the file (MODE==2). + It matches the streambuf::seekoff virtual function. + It is also used for the ANSI fseek function. */ +typedef _IO_fpos_t (*_IO_seekoff_t) + __P((_IO_FILE* FP, _IO_off_t OFF, int DIR, int MODE)); +#define _IO_SEEKOFF(FP, OFF, DIR, MODE) JUMP3(__seekoff, FP, OFF, DIR, MODE) + +/* The 'seekpos' hook also moves the stream position, + but to an absolute position given by a fpos_t (seekpos). + It matches the streambuf::seekpos virtual function. + It is also used for the ANSI fgetpos and fsetpos functions. */ +/* The _IO_seek_cur and _IO_seek_end options are not allowed. */ +typedef _IO_fpos_t (*_IO_seekpos_t) __P((_IO_FILE*, _IO_fpos_t, int)); +#define _IO_SEEKPOS(FP, POS, FLAGS) JUMP2(__seekpos, FP, POS, FLAGS) + +/* The 'setbuf' hook gives a buffer to the file. + It matches the streambuf::setbuf virtual function. */ +typedef _IO_FILE* (*_IO_setbuf_t) __P((_IO_FILE*, char *, _IO_ssize_t)); +#define _IO_SETBUF(FP, BUFFER, LENGTH) JUMP2(__setbuf, FP, BUFFER, LENGTH) + +/* The 'sync' hook attempts to synchronize the internal data structures + of the file with the external state. + It matches the streambuf::sync virtual function. */ +typedef int (*_IO_sync_t) __P((_IO_FILE*)); +#define _IO_SYNC(FP) JUMP0(__sync, FP) + +/* The 'doallocate' hook is used to tell the file to allocate a buffer. + It matches the streambuf::doallocate virtual function, which is not + in the ANSI/ISO C++ standard, but is part traditional implementations. */ +typedef int (*_IO_doallocate_t) __P((_IO_FILE*)); +#define _IO_DOALLOCATE(FP) JUMP0(__doallocate, FP) + +/* The following four hooks (sysread, syswrite, sysclose, sysseek, and + sysstat) are low-level hooks specific to this implementation. + There is no correspondance in the ANSI/ISO C++ standard library. + The hooks basically correspond to the Unix system functions + (read, write, close, lseek, and stat) except that a _IO_FILE* + parameter is used instead of a integer file descriptor; the default + implementation used for normal files just calls those functions. + The advantage of overriding these functions instead of the higher-level + ones (underflow, overflow etc) is that you can leave all the buffering + higher-level functions. */ + +/* The 'sysread' hook is used to read data from the external file into + an existing buffer. It generalizes the Unix read(2) function. + It matches the streambuf::sys_read virtual function, which is + specific to this implementaion. */ +typedef _IO_ssize_t (*_IO_read_t) __P((_IO_FILE*, void*, _IO_ssize_t)); +#define _IO_SYSREAD(FP, DATA, LEN) JUMP2(__read, FP, DATA, LEN) + +/* The 'syswrite' hook is used to write data from an existing buffer + to an external file. It generalizes the Unix write(2) function. + It matches the streambuf::sys_write virtual function, which is + specific to this implementaion. */ +typedef _IO_ssize_t (*_IO_write_t) __P((_IO_FILE*,const void*,_IO_ssize_t)); +#define _IO_SYSWRITE(FP, DATA, LEN) JUMP2(__write, FP, DATA, LEN) + +/* The 'sysseek' hook is used to re-position an external file. + It generalizes the Unix lseek(2) function. + It matches the streambuf::sys_seek virtual function, which is + specific to this implementaion. */ +typedef _IO_fpos_t (*_IO_seek_t) __P((_IO_FILE*, _IO_off_t, int)); +#define _IO_SYSSEEK(FP, OFFSET, MODE) JUMP2(__seek, FP, OFFSET, MODE) + +/* The 'sysclose' hook is used to finalize (close, finish up) an + external file. It generalizes the Unix close(2) function. + It matches the streambuf::sys_close virtual function, which is + specific to this implementation. */ +typedef int (*_IO_close_t) __P((_IO_FILE*)); /* finalize */ +#define _IO_SYSCLOSE(FP) JUMP0(__close, FP) + +/* The 'sysstat' hook is used to get information about an external file + into a struct stat buffer. It generalizes the Unix fstat(2) call. + It matches the streambuf::sys_stat virtual function, which is + specific to this implementaion. */ +typedef int (*_IO_stat_t) __P((_IO_FILE*, void*)); +#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 contains a pointer to the function jump table used. + 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; + const struct _IO_jump_t *vtable; +}; + +/* Generic functions */ + +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(fp) ((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)); + +/* 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 + +/* 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, 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/gnu/lib/libg++/libio/osform.cc b/gnu/lib/libg++/libio/osform.cc new file mode 100644 index 00000000000..8c0011703da --- /dev/null +++ b/gnu/lib/libg++/libio/osform.cc @@ -0,0 +1,54 @@ +/* +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 <iostream.h> +#include <stdarg.h> + +ostream& ostream::form(const char *format ...) +{ + if (opfx()) { + va_list ap; + va_start(ap, format); + _IO_vfprintf(rdbuf(), format, ap); + va_end(ap); + } + return *this; +} + +ostream& ostream::vform(const char *format, _IO_va_list args) +{ + if (opfx()) + _IO_vfprintf(rdbuf(), format, args); + return *this; +} + +ostream& ostream::operator<<(const void *p) +{ + if (opfx()) { + form("%p", p); + osfx(); + } + return *this; +} diff --git a/gnu/lib/libg++/libio/ostream.h b/gnu/lib/libg++/libio/ostream.h new file mode 100644 index 00000000000..f54ec1de9a1 --- /dev/null +++ b/gnu/lib/libg++/libio/ostream.h @@ -0,0 +1,25 @@ +/* +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 <stream.h> diff --git a/gnu/lib/libg++/libio/outfloat.c b/gnu/lib/libg++/libio/outfloat.c new file mode 100644 index 00000000000..a74b1a2c3e1 --- /dev/null +++ b/gnu/lib/libg++/libio/outfloat.c @@ -0,0 +1,204 @@ +/* +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" + +/* Format floating-point number and print them. + Return number of chars printed, or EOF on error. + + sign_mode == '+' : print "-" or "+" + sign_mode == ' ' : print "-" or " " + sign_mode == '\0' : print "-' or "" +*/ + +int +DEFUN(_IO_outfloat, (value, sb, type, width, precision, flags, + sign_mode, fill), + double value AND _IO_FILE *sb AND int type AND int width + AND int precision AND int flags AND int sign_mode AND int fill) +{ + int count = 0; +#define PUT(x) do {if (_IO_putc(x, sb) < 0) goto error; count++;} while (0) +#define PUTN(p, n) \ + do {int _n=n; count+=_n; if (_IO_sputn(sb, p,_n) != _n) goto error;} while(0) +#define PADN(fill, n) \ + do {int _n = n; count+=_n; if (_IO_padn(sb, fill, _n) != _n) goto error;} while (0) + int pad_kind = flags & (_IO_LEFT|_IO_RIGHT|_IO_INTERNAL); + int skip_zeroes = 0; + int show_dot = (flags & _IO_SHOWPOINT) != 0; + int decpt; + int sign; + int mode; + int exponent_size; + int print_sign; + int trailing_zeroes, useful_digits; + int padding, unpadded_width; + char *p; + char *exponent_start; + register int i; +#define EBUF_SIZE 12 +#define EBUF_END &ebuf[EBUF_SIZE] + char ebuf[EBUF_SIZE]; + char *end; + int exp = 0; + switch (type) + { + case 'f': + mode = 3; + break; + case 'e': + case 'E': + exp = type; + mode = 2; + if (precision != 999) + precision++; /* Add one to include digit before decimal point. */ + break; + case 'g': + case 'G': + exp = type == 'g' ? 'e' : 'E'; + if (precision == 0) precision = 1; + if (!(flags & _IO_SHOWPOINT)) + skip_zeroes = 1; + type = 'g'; + mode = 2; + break; + } + /* Do the actual convension */ + if (precision == 999 && mode != 3) + mode = 0; + p = _IO_dtoa(value, mode, precision, &decpt, &sign, &end); + useful_digits = end-p; + exponent_start = EBUF_END; + if (mode == 0) + precision = useful_digits; + /* Check if we need to emit an exponent. */ + if (mode != 3 && decpt != 9999) + { + i = decpt - 1; + if ((type != 'g' && type != 'F') || i < -4 || i >= precision) + { + /* Print the exponent into ebuf. + We write ebuf in reverse order (right-to-left). */ + char sign; + if (i >= 0) + sign = '+'; + else + sign = '-', i = -i; + /* Note: ANSI requires at least 2 exponent digits. */ + do { + *--exponent_start = (i % 10) + '0'; + i /= 10; + } while (i >= 10); + *--exponent_start = i + '0'; + *--exponent_start = sign; + *--exponent_start = exp; + } + } + exponent_size = EBUF_END - exponent_start; + if (mode == 1) + precision = 1; + /* If we print an exponent, always show just one digit before point. */ + if (exponent_size) + decpt = 1; + if (decpt == 9999) + { /* Infinity or NaN */ + decpt = useful_digits; + precision = 0; + show_dot = 0; + } + + /* dtoa truncates trailing zeroes. Set the variable trailing_zeroes to + the number of 0's we have to add (after the decimal point). */ + if (skip_zeroes) + trailing_zeroes = 0; + else if (type == 'f') + trailing_zeroes = useful_digits <= decpt ? precision + : precision-(useful_digits-decpt); + else if (exponent_size) /* 'e' 'E' or 'g' format using exponential notation*/ + trailing_zeroes = precision - useful_digits; + else /* 'g' format not using exponential notation. */ + trailing_zeroes = useful_digits <= decpt ? precision - decpt + : precision-useful_digits; + if (trailing_zeroes < 0) trailing_zeroes = 0; + + if (trailing_zeroes != 0 || useful_digits > decpt) + show_dot = 1; + if (sign_mode == 0) + print_sign = sign ? '-' : 0; + else if (sign_mode == '+') + print_sign = sign ? '-' : '+'; + else /* if (sign_mode == ' ') */ + print_sign = sign ? '-' : ' '; + + /* Calculate the width (before padding). */ + unpadded_width = + (print_sign != 0) + trailing_zeroes + exponent_size + show_dot + + useful_digits + + (decpt > useful_digits ? decpt - useful_digits + : decpt > 0 ? 0 : 1 - decpt); + + padding = width > unpadded_width ? width - unpadded_width : 0; + if (padding > 0 && pad_kind != _IO_LEFT && pad_kind != _IO_INTERNAL) + PADN(fill, padding); /* Default (right) adjust */ + if (print_sign) + PUT(print_sign); + if (pad_kind == _IO_INTERNAL && padding > 0) + PADN(fill, padding); + if (decpt > 0) + { + if (useful_digits >= decpt) + PUTN(p, decpt); + else + { + PUTN(p, useful_digits); + PADN('0', decpt-useful_digits); + } + if (show_dot) + { + PUT('.'); + /* Print digits after the decimal point. */ + if (useful_digits > decpt) + PUTN(p + decpt, useful_digits-decpt); + } + } + else + { + PUT('0'); + if (show_dot) + { + PUT('.'); + PADN('0', -decpt); + /* Print digits after the decimal point. */ + PUTN(p, useful_digits); + } + } + PADN('0', trailing_zeroes); + if (exponent_size) + PUTN(exponent_start, exponent_size); + if (pad_kind == _IO_LEFT && padding > 0) /* Left adjustment*/ + PADN(fill, padding); + return count; + error: + return EOF; +} diff --git a/gnu/lib/libg++/libio/parsestream.cc b/gnu/lib/libg++/libio/parsestream.cc new file mode 100644 index 00000000000..320afd06d9b --- /dev/null +++ b/gnu/lib/libg++/libio/parsestream.cc @@ -0,0 +1,317 @@ +/* This is part of libio/iostream, providing -*- C++ -*- input/output. +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. + +Written by Per Bothner (bothner@cygnus.com). */ + +#ifdef __GNUG__ +#pragma implementation +#endif +#include "libioP.h" +#include "parsestream.h" +#include <stdlib.h> + +streambuf* parsebuf::setbuf(char*, int) +{ + return NULL; +} + +int parsebuf::tell_in_line() +{ + return 0; +} + +int parsebuf::pbackfail(int c) +{ + if (c == EOF) + return 0; + if (seekoff(-1, ios::cur) == EOF) + return EOF; + return (unsigned char)c; +} + +char* parsebuf::current_line() { return NULL; } + +streampos parsebuf::seekoff(streamoff offset, _seek_dir dir, int) +{ + // Make offset relative to line start. + switch (dir) { + case ios::beg: + offset -= pos_at_line_start; + break; + case ios::cur: + offset += tell_in_line(); + break; + default: + return EOF; + } + if (offset < -1) + return EOF; + if (offset > _line_length + 1) + return EOF; + return seek_in_line(offset) + pos_at_line_start; +} + +// string_parsebuf invariants: +// The reserve ares (base() .. ebuf()) is always the entire string. +// The get area (eback() .. egptr()) is the extended current line +// (i.e. with the '\n' at either end, if these exist). + +string_parsebuf::string_parsebuf(char *buf, int len, + int delete_at_close /* = 0*/) +: parsebuf() +{ + setb(buf, buf+len, delete_at_close); + register char *ptr = buf; + while (ptr < ebuf() && *ptr != '\n') ptr++; + _line_length = ptr - buf; + setg(buf, buf, ptr); +} + +int string_parsebuf::underflow() +{ + register char* ptr = egptr(); // Point to end of current_line + do { + int i = right() - ptr; + if (i <= 0) + return EOF; + ptr++; i--; // Skip '\n'. + char *line_start = ptr; + while (ptr < right() && *ptr == '\n') ptr++; + setg(line_start-1, line_start, ptr + (ptr < right())); + pos_at_line_start = line_start - left(); + _line_length = ptr - line_start; + __line_number++; + } while (gptr() == ptr); + return *gptr(); +} + +char* string_parsebuf::current_line() +{ + char *ptr = eback(); + if (__line_number > 0) + ptr++; // Skip '\n' at end of previous line. + return ptr; +} + +int string_parsebuf::tell_in_line() +{ + int offset = gptr() - eback(); + if (__line_number > 0) + offset--; + return offset; +} + +int string_parsebuf::seek_in_line(int i) +{ + int delta = i - tell_in_line(); + gbump(delta); // FIXME: Needs error (bounds) checking! + return i; +} + +static const char NewLine[1] = { '\n' }; + +general_parsebuf::general_parsebuf(streambuf *buf, int delete_arg_buf) + : parsebuf() +{ + delete_buf = delete_arg_buf; + sbuf = buf; + int buf_size = 128; + char* buffer = ALLOC_BUF(buf_size); + setb(buffer, buffer+buf_size, 1); +// setg(buffer, buffer, buffer); +} + +general_parsebuf::~general_parsebuf() +{ + if (delete_buf) + delete sbuf; +} + +int general_parsebuf::underflow() +{ + register char *ptr = base(); + int has_newline = eback() < gptr() && gptr()[-1] == '\n'; + if (has_newline) + *ptr++ = '\n'; + register streambuf *sb = sbuf; + register int ch; + for (;;) { + ch = sb->sbumpc(); + if (ch == EOF) + break; + if (ptr == ebuf()) { + int old_size = ebuf() - base(); + char *new_buffer = new char[old_size * 2]; + memcpy(new_buffer, base(), old_size); + setb(new_buffer, new_buffer + 2 * old_size, 1); + ptr = new_buffer + old_size; + } + *ptr++ = ch; + if (ch == '\n') + break; + } + char *cur_pos = base() + has_newline; + pos_at_line_start += _line_length + 1; + _line_length = ptr - cur_pos; + if (ch != EOF || _line_length > 0) + __line_number++; + setg(base(), cur_pos, ptr); + return ptr == cur_pos ? EOF : cur_pos[0]; +} + +char* general_parsebuf::current_line() +{ + char* ret = base(); + if (__line_number > 1) + ret++; // Move past '\n' from end of previous line. + return ret; +} + +int general_parsebuf::tell_in_line() +{ + int off = gptr() - base(); + if (__line_number > 1) + off--; // Subtract 1 for '\n' from end of previous line. + return off; +} + +int general_parsebuf::seek_in_line(int i) +{ + if (__line_number == 0) + (void)general_parsebuf::underflow(); + if (__line_number > 1) + i++; // Add 1 for '\n' from end of previous line. + if (i < 0) i = 0; + int len = egptr() - eback(); + if (i > len) i = len; + setg(base(), base() + i, egptr()); + return i; +} + +func_parsebuf::func_parsebuf(CharReader func, void *argm) : parsebuf() +{ + read_func = func; + arg = argm; + buf_start = NULL; + buf_end = NULL; + setb((char*)NewLine, (char*)NewLine+1, 0); + setg((char*)NewLine, (char*)NewLine+1, (char*)NewLine+1); + backed_up_to_newline = 0; +} + +int func_parsebuf::tell_in_line() +{ + if (buf_start == NULL) + return 0; + if (egptr() != (char*)NewLine+1) + // Get buffer was line buffer. + return gptr() - buf_start; + if (backed_up_to_newline) + return -1; // Get buffer is '\n' preceding current line. + // Get buffer is '\n' following current line. + return (buf_end - buf_start) + (gptr() - (char*)NewLine); +} + +char* func_parsebuf::current_line() +{ + return buf_start; +} + +int func_parsebuf::seek_in_line(int i) +{ + if (i < 0) { + // Back up to preceding '\n'. + if (i < -1) i = -1; + backed_up_to_newline = 1; + setg((char*)NewLine, (char*)NewLine+(i+1), (char*)NewLine+1); + return i; + } + backed_up_to_newline = 0; + int line_length = buf_end-buf_start; + if (i <= line_length) { + setg(buf_start, buf_start+i, buf_end); + return i; + } + i -= line_length; + if (i > 0) i = 1; + setg((char*)NewLine, (char*)NewLine+i, (char*)NewLine+1); + return line_length + i; +} + +int func_parsebuf::underflow() +{ + retry: + if (gptr() < egptr()) + return *gptr(); + if (gptr() != (char*)NewLine+1) { + // Get buffer was line buffer. Move to following '\n'. + setg((char*)NewLine, (char*)NewLine, (char*)NewLine+1); + return *gptr(); + } + if (backed_up_to_newline) + // Get buffer was '\n' preceding current line. Move to current line. + backed_up_to_newline = 0; + else { + // Get buffer was '\n' following current line. Read new line. + if (buf_start) free(buf_start); + char *str = (*read_func)(arg); + buf_start = str; + if (str == NULL) + return EOF; + // Initially, _line_length == -1, so pos_at_line_start becomes 0. + pos_at_line_start += _line_length + 1; + _line_length = strlen(str); + buf_end = str + _line_length; + __line_number++; + } + setg(buf_start, buf_start, buf_end); + goto retry; +} + +#if 0 +size_t parsebuf::line_length() +{ + if (current_line_length == (size_t)(-1)) // Initial value; + (void)sgetc(); + return current_line_length; +} +#endif + +int parsebuf::seek_in_line(int i) +{ +#if 1 + abort(); + return i; // Suppress warnings. +#else + if (i > 0) { + size_t len = line_length(); + if ((unsigned)i > len) i = len; + } + else if (i < -1) i = -1; + int new_pos = seekoff(pos_at_line_start + i, ios::beg); + if (new_pos == EOF) + return tell_in_line(); + else return new_pos - pos_at_line_start; +#endif +} diff --git a/gnu/lib/libg++/libio/parsestream.h b/gnu/lib/libg++/libio/parsestream.h new file mode 100644 index 00000000000..326ab87a809 --- /dev/null +++ b/gnu/lib/libg++/libio/parsestream.h @@ -0,0 +1,156 @@ +/* This is part of libio/iostream, providing -*- C++ -*- input/output. +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. + +Written by Per Bothner (bothner@cygnus.com). */ + +#ifndef PARSESTREAM_H +#define PARSESTREAM_H +#ifdef __GNUG__ +#pragma interface +#endif +#include "streambuf.h" + +extern "C++" { +// A parsebuf is a streambuf optimized for scanning text files. +// It keeps track of line and column numbers. +// It is guaranteed to remember the entire current line, +// as well the '\n'-s on either side of it (if they exist). +// You can arbitrarily seek (or unget) within this extended line. +// Other backward seeks are not supported. +// Normal read semantics are supported (and hence istream operators like >>). + +class parsebuf : public streambuf { + protected: + _IO_fpos_t pos_at_line_start; + long _line_length; + unsigned long __line_number; + char *buf_start; + char *buf_end; + + public: + parsebuf *chain; + + // Return column number (raw - don't handle tabs etc). + // Retult can be -1, meaning: at '\n' before current line. + virtual int tell_in_line(); + + // seek to (raw) column I in current line. + // Result is new (raw) column position - differs from I if unable to seek. + // Seek to -1 tries to seek to before previous LF. + virtual int seek_in_line(int i); + + // Note: there is no "current line" initially, until something is read. + + // Current line number, starting with 0. + // If tell_in_line()==-1, then line number of next line. + int line_number() { return __line_number; } + + // Length of current line, not counting either '\n'. + int line_length() { return _line_length; } + // Current line - not a copy, so file ops may trash it. + virtual char* current_line(); + virtual streampos seekoff(streamoff, _seek_dir, int mode=ios::in|ios::out); + virtual streambuf* setbuf(char* p, int len); + protected: + parsebuf() { chain= NULL; + __line_number = 0; pos_at_line_start = 0; _line_length = -1; } + virtual int pbackfail(int c); +}; + +// A string_parsebuf is a parsebuf whose source is a fixed string. + +class string_parsebuf : public parsebuf { + public: + int do_delete; + string_parsebuf(char *str, int len, int delete_at_close=0); + virtual int underflow(); + virtual char* current_line(); + virtual int seek_in_line(int i); + virtual int tell_in_line(); + char *left() const { return base(); } + char *right() const { return ebuf(); } +// streampos seekoff(streamoff, _seek_dir, int); +}; + +// A func_parsebuf calls a given function to get new input. +// Each call returns an entire NUL-terminated line (without the '\n'). +// That line has been allocated with malloc(), not new. +// The interface is tailored to the GNU readline library. +// Example: +// char* DoReadLine(void* arg) +// { +// char *line = readline((char*)arg); /* 'arg' is used as prompt. */ +// if line == NULL) { putc('\n', stderr); return NULL; } +// if (line[0] != '\0') add_history(line); +// return line; +// } +// char PromptBuffer[100] = "> "; +// func_parsebuf my_stream(DoReadLine, PromptBuffer); + +typedef char *(*CharReader)(void *arg); +class istream; + +class func_parsebuf : public parsebuf { + public: + void *arg; + CharReader read_func; + int backed_up_to_newline; + func_parsebuf(CharReader func, void *argm = NULL); + int underflow(); + virtual int tell_in_line(); + virtual int seek_in_line(int i); + virtual char* current_line(); +}; + +// A general_parsebuf is a parsebuf which gets its input from some +// other streambuf. It explicitly buffers up an entire line. + +class general_parsebuf : public parsebuf { + public: + streambuf *sbuf; + int delete_buf; // Delete sbuf when destroying this. + general_parsebuf(streambuf *buf, int delete_arg_buf = 0); + int underflow(); + virtual int tell_in_line(); + virtual int seek_in_line(int i); + ~general_parsebuf(); + virtual char* current_line(); +}; + +#if 0 +class parsestream : public istream { + streammarker marks[2]; + short _first; // of the two marks; either 0 or 1 + int _lineno; + int first() { return _first; } + int second() { return 1-_first; } + int line_length() { marks[second].delta(marks[first]); } + int line_length() { marks[second].delta(marks[first]); } + int seek_in_line(int i); + int tell_in_line(); + int line_number(); +}; +#endif +} // extern "C++" +#endif /*!defined(PARSESTREAM_H)*/ diff --git a/gnu/lib/libg++/libio/pfstream.cc b/gnu/lib/libg++/libio/pfstream.cc new file mode 100644 index 00000000000..3fa93c958f8 --- /dev/null +++ b/gnu/lib/libg++/libio/pfstream.cc @@ -0,0 +1,92 @@ +/* This is part of libio/iostream, providing -*- C++ -*- input/output. +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. */ + +/* Written by Per Bothner (bothner@cygnus.com). */ + +#ifdef __GNUG__ +#pragma implementation +#endif +#include "libioP.h" +#include <pfstream.h> +#include <procbuf.h> + +ipfstream::ipfstream(const char *name, int mode, int prot) +{ + const char* p; + + // Look for '| command' (as used by ftp). + for (p = name; *p == ' ' || *p == '\t'; p++) ; + if (*p == '|') { + procbuf *pbuf = new procbuf(); + init(pbuf); + if (!pbuf->open(p+1, mode)) + set(ios::badbit); + return; + } + + // Look for 'command |' + while (*p) p++; // Point to last + while (p[-1] == ' ' || p[-1] == '\t' || p[-1] == '\n') p--; + if (p[-1] == '|') { + // Must remove the final '|'. + p--; +#if !defined (__GNUC__) || defined (__STRICT_ANSI__) + char *command = new char[p-name+1]; +#else + char command[p-name+1]; +#endif + memcpy(command, name, p-name); + command[p-name] = '\0'; + + procbuf *pbuf = new procbuf(); + if (pbuf->open(command, mode)) + set(ios::badbit); +#if !defined (__GNUC__) || defined (__STRICT_ANSI__) + delete command; +#endif + return; + } + + init(new filebuf()); + if (!rdbuf()->open(name, mode, prot)) + set(ios::badbit); +} + +opfstream::opfstream(const char *name, int mode, int prot) +{ + const char *p; + // Look for '| command'. + for (p = name; *p == ' ' || *p == '\t'; p++) ; + if (*p == '|') { + procbuf *pbuf = new procbuf(); + init(pbuf); + if (!pbuf->open(p+1, mode)) + set(ios::badbit); + } + else { + init(new filebuf()); + if (!rdbuf()->open(name, mode, prot)) + set(ios::badbit); + } +} diff --git a/gnu/lib/libg++/libio/pfstream.h b/gnu/lib/libg++/libio/pfstream.h new file mode 100644 index 00000000000..3c5458baaa9 --- /dev/null +++ b/gnu/lib/libg++/libio/pfstream.h @@ -0,0 +1,59 @@ +/* This is part of libio/iostream, providing -*- C++ -*- input/output. +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. */ + +/* Written by Per Bothner (bothner@cygnus.com). */ + +#ifndef _PFSTREAM_H +#define _PFSTREAM_H +#ifdef __GNUG__ +#pragma interface +#endif +#include <fstream.h> + +extern "C++" { +// ipfstream foo("NAME") is like: ifstream foo("NAME"). However, +// if NAME starts *or ends* with a '|', the remainder of NAME is +// evaluated as a shell command (using a procbuf), and all input +// read from foo is whatever that shell writes to its standard output. +// E.g. ipfstream foo("|zcat foo.Z") or ipfstream foo("zcat foo.Z|") +// (These two forms are equivalent.) + +class ipfstream : public ifstream { + public: + ipfstream(const char *name, int mode=ios::in, int prot=0664); +}; + +// opfstream foo("NAME") is like: ofstream foo("NAME"). +// However, if NAME starts with a '|', the remainder of NAME is +// evaluated as a shell command (using a procbuf), and all output +// written to foo is piped to the standard input of that shell. +// E.g. opfstream foo("|more"); + +class opfstream : public ofstream { + public: + opfstream(const char *name, int mode=ios::out, int prot=0664); +}; +} // extern "C++" +#endif /*!_PFSTREAM_H*/ + diff --git a/gnu/lib/libg++/libio/procbuf.cc b/gnu/lib/libg++/libio/procbuf.cc new file mode 100644 index 00000000000..1c79ce4ce0f --- /dev/null +++ b/gnu/lib/libg++/libio/procbuf.cc @@ -0,0 +1,55 @@ +/* This is part of libio/iostream, providing -*- C++ -*- input/output. +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. */ + +/* Written by Per Bothner (bothner@cygnus.com). */ + +#ifdef __GNUG__ +#pragma implementation +#endif + +#define _POSIX_SOURCE +#include "libioP.h" +#include "procbuf.h" + +procbuf::procbuf(const char *command, int mode) : filebuf() +{ + _IO_proc_open(this, command, (mode & ios::in) ? "r" : "w"); +} + +procbuf *procbuf::open(const char *command, int mode) +{ + return (procbuf*)_IO_proc_open(this, command, (mode & ios::in) ? "r" : "w"); +} + +/* #define USE_SIGMASK */ + +int procbuf::sys_close() +{ + return _IO_proc_close(this); +} + +procbuf::~procbuf() +{ + close(); +} diff --git a/gnu/lib/libg++/libio/procbuf.h b/gnu/lib/libg++/libio/procbuf.h new file mode 100644 index 00000000000..b361a6a7c84 --- /dev/null +++ b/gnu/lib/libg++/libio/procbuf.h @@ -0,0 +1,50 @@ +/* This is part of libio/iostream, providing -*- C++ -*- input/output. +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. */ + +/* Written by Per Bothner (bothner@cygnus.com). */ + +#ifndef _PROCBUF_H +#define _PROCBUF_H +#ifdef __GNUG__ +#pragma interface +#endif + +#include <streambuf.h> + +extern "C++" { +class procbuf : public filebuf { + /* Following fields must match those in struct _IO_proc_file */ + _IO_pid_t _pid; + procbuf *_next; + public: + procbuf() : filebuf() { } + procbuf(const char *command, int mode); + procbuf* open(const char *command, int mode); + procbuf *close() { return (procbuf*)filebuf::close(); } + virtual int sys_close(); + ~procbuf(); +}; +} // extern "C++" + +#endif /* !_PROCBUF_H */ diff --git a/gnu/lib/libg++/libio/sbform.cc b/gnu/lib/libg++/libio/sbform.cc new file mode 100644 index 00000000000..c17bd08db15 --- /dev/null +++ b/gnu/lib/libg++/libio/sbform.cc @@ -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 "streambuf.h" +#include <stdarg.h> + +int streambuf::vform(char const *fmt0, _IO_va_list ap) +{ + return _IO_vfprintf(this, fmt0, ap); +} +int streambuf::form(char const *format ...) +{ + va_list ap; + va_start(ap, format); + int count = _IO_vfprintf(this, format, ap); + va_end(ap); + return count; +} diff --git a/gnu/lib/libg++/libio/sbgetline.cc b/gnu/lib/libg++/libio/sbgetline.cc new file mode 100644 index 00000000000..700e2ec7afc --- /dev/null +++ b/gnu/lib/libg++/libio/sbgetline.cc @@ -0,0 +1,31 @@ +/* +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 "streambuf.h" + +long streambuf::sgetline(char* buf, _IO_size_t n, char delim, int extract_delim) +{ + return _IO_getline(this, buf, n, delim, extract_delim); +} diff --git a/gnu/lib/libg++/libio/sbscan.cc b/gnu/lib/libg++/libio/sbscan.cc new file mode 100644 index 00000000000..c0ec35c53db --- /dev/null +++ b/gnu/lib/libg++/libio/sbscan.cc @@ -0,0 +1,45 @@ + +/* +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 "streambuf.h" +#include <stdarg.h> + +int streambuf::vscan(char const *fmt0, _IO_va_list ap, ios* stream /* = NULL*/) +{ + int errcode = 0; + int count = _IO_vfscanf(this, fmt0, ap, &errcode); + if (stream) + stream->setstate((ios::iostate)errcode); + return count; +} +int streambuf::scan(char const *format ...) +{ + va_list ap; + va_start(ap, format); + int count = _IO_vfscanf(this, format, ap, NULL); + va_end(ap); + return count; +} diff --git a/gnu/lib/libg++/libio/shlib_version b/gnu/lib/libg++/libio/shlib_version new file mode 100644 index 00000000000..97c9f92d6b8 --- /dev/null +++ b/gnu/lib/libg++/libio/shlib_version @@ -0,0 +1,2 @@ +major=0 +minor=0 diff --git a/gnu/lib/libg++/libio/stdfiles.c b/gnu/lib/libg++/libio/stdfiles.c new file mode 100644 index 00000000000..1d0ef85be90 --- /dev/null +++ b/gnu/lib/libg++/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/gnu/lib/libg++/libio/stdiostream.cc b/gnu/lib/libg++/libio/stdiostream.cc new file mode 100644 index 00000000000..80db5e59bfd --- /dev/null +++ b/gnu/lib/libg++/libio/stdiostream.cc @@ -0,0 +1,159 @@ +/* This is part of libio/iostream, providing -*- C++ -*- input/output. +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. */ + +/* Written by Per Bothner (bothner@cygnus.com). */ + +#ifdef __GNUG__ +#pragma implementation +#endif + +#include <stdiostream.h> +#include "libioP.h" + +// A stdiobuf is "tied" to a FILE object (as used by the stdio package). +// Thus a stdiobuf is always synchronized with the corresponding FILE, +// though at the cost of some overhead. (If you use the implementation +// of stdio supplied with this library, you don't need stdiobufs.) +// This implementation inherits from filebuf, but implement the virtual +// functions sys_read/..., using the stdio functions fread/... instead +// of the low-level read/... system calls. This has the advantage that +// we get all of the nice filebuf semantics automatically, though +// with some overhead. + + +#ifndef SEEK_SET +#define SEEK_SET 0 +#endif +#ifndef SEEK_CUR +#define SEEK_CUR 1 +#endif +#ifndef SEEK_END +#define SEEK_END 2 +#endif + +stdiobuf::stdiobuf(FILE *f) : filebuf(fileno(f)) +{ + _file = f; + // Turn off buffer in stdiobuf. Instead, rely on buffering in (FILE). + // Thus the stdiobuf will be synchronized with the FILE. + setbuf(NULL, 0); +} + +stdiobuf::~stdiobuf() +{ + /* Only needed if we're buffered. Not buffered is the default. */ + _IO_do_flush((_IO_FILE*)this); +} + +streamsize stdiobuf::sys_read(char* buf, streamsize size) +{ + // A minor optimization, but it makes a noticable difference. + // A bigger optimization would be to write stdiobuf::underflow, + // but that has some modularity disadvantages. Re-evaluate that + // after we have gotten rid of the double indirection. FIXME + if (size == 1) + { + register ch = getc(_file); + if (ch == EOF) + return 0; + *buf = (char)ch; + return 1; + } + else + return fread(buf, 1, size, _file); +} + +streamsize stdiobuf::sys_write(const char *buf, streamsize n) +{ + _IO_ssize_t count = fwrite(buf, 1, n, _file); + if (_offset >= 0) + _offset += n; + return count; +} + +streampos stdiobuf::sys_seek(streamoff offset, _seek_dir dir) +{ + // Normally, equivalent to: fdir=dir + int fdir = + (dir == ios::beg) ? SEEK_SET : + (dir == ios::cur) ? SEEK_CUR : + (dir == ios::end) ? SEEK_END : + dir; + return fseek(_file, offset, fdir); +} + +int stdiobuf::sys_close() +{ + int status = fclose(_file); + _file = NULL; + return status; +} + +int stdiobuf::sync() +{ + if (_IO_do_flush((_IO_FILE*)this)) + return EOF; + if (!(xflags() & _IO_NO_WRITES)) + if (fflush(_file)) + return EOF; + return 0; +} + +int stdiobuf::overflow(int c /* = EOF*/) +{ + if (filebuf::overflow(c) == EOF) + return EOF; + if (c != EOF) + return c; + return fflush(_file); +} + +streamsize stdiobuf::xsputn(const char* s, streamsize n) +{ + if (buffered ()) + { + // The filebuf implementation of sputn loses. + return streambuf::xsputn(s, n); + } + else + return fwrite (s, 1, n, _file); +} + +void stdiobuf::buffered (int b) +{ + if (b) + { + if (_flags & _IO_UNBUFFERED) + { /* Was unbuffered, make it buffered. */ + _flags &= ~_IO_UNBUFFERED; + } + } + else + { + if (!(_flags & _IO_UNBUFFERED)) + { /* Was buffered, make it unbuffered. */ + setbuf(NULL, 0); + } + } +} diff --git a/gnu/lib/libg++/libio/stdiostream.h b/gnu/lib/libg++/libio/stdiostream.h new file mode 100644 index 00000000000..73d49f96c22 --- /dev/null +++ b/gnu/lib/libg++/libio/stdiostream.h @@ -0,0 +1,79 @@ +/* This is part of libio/iostream, providing -*- C++ -*- input/output. +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. */ + +/* Written by Per Bothner (bothner@cygnus.com). */ + +#ifndef _STDIOSTREAM_H +#define _STDIOSTREAM_H + +#ifdef __GNUG__ +#pragma interface +#endif + +#include <iostream.h> +#include <stdio.h> + +extern "C++" { +class stdiobuf : public filebuf { + protected: + FILE *_file; + public: + FILE* stdiofile() const { return _file; } + stdiobuf(FILE *); + ~stdiobuf(); + int buffered () const { return _flags & _IO_UNBUFFERED ? 0 : 1; } + void buffered (int); + virtual streamsize sys_read(char*, streamsize); + virtual streampos sys_seek(streamoff, _seek_dir); + virtual streamsize sys_write(const char*, streamsize); + virtual int sys_close(); + virtual int sync(); + virtual int overflow(int c = EOF); + streamsize xsputn(const char* s, streamsize n); +}; + +class istdiostream : public istream +{ +private: + stdiobuf _file; +public: + istdiostream (FILE* __f) : _file(__f), istream() { init(&_file); } + stdiobuf* rdbuf()/* const */ { return &_file; } + int buffered () const { return _file.buffered (); } + void buffered (int _i) { _file.buffered (_i); } +}; + +class ostdiostream : public ostream +{ +private: + stdiobuf _file; +public: + ostdiostream (FILE* __f) : _file(__f), ostream() { init(&_file); } + stdiobuf* rdbuf() /* const */ { return &_file; } + int buffered () const { return _file.buffered (); } + void buffered (int _i) { _file.buffered (_i); } +}; +} // extern "C++" + +#endif /* !_STDIOSTREAM_H */ diff --git a/gnu/lib/libg++/libio/stdstrbufs.cc b/gnu/lib/libg++/libio/stdstrbufs.cc new file mode 100644 index 00000000000..8af259988a5 --- /dev/null +++ b/gnu/lib/libg++/libio/stdstrbufs.cc @@ -0,0 +1,115 @@ +/* +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. */ + + +/* This file provides definitions of _IO_stdin, _IO_stdout, and _IO_stderr + for C++ code. Compare stdfiles.c. + (The difference is that here the vtable field is set to + point to builtinbuf's vtable, so the objects are effectively + of class builtinbuf.) */ + +#include "libioP.h" +#include <stdio.h> + +#if !defined(filebuf_vtable) && defined(__cplusplus) +#ifdef __GNUC__ +extern char filebuf_vtable[] + asm (_G_VTABLE_LABEL_PREFIX +#if _G_VTABLE_LABEL_HAS_LENGTH + "7" +#endif + "filebuf"); +#else /* !__GNUC__ */ +#if _G_VTABLE_LABEL_HAS_LENGTH +#define filebuf_vtable _G_VTABLE_LABEL_PREFIX_ID##7filebuf +#else +#define filebuf_vtable _G_VTABLE_LABEL_PREFIX_ID##filebuf +#endif +extern char filebuf_vtable[]; +#endif /* !__GNUC__ */ +#endif /* !defined(filebuf_vtable) && defined(__cplusplus) */ + +#ifndef STD_VTABLE +#define STD_VTABLE (const struct _IO_jump_t *)filebuf_vtable +#endif + +#define DEF_STDFILE(NAME, FD, CHAIN, FLAGS) \ + struct _IO_FILE_plus NAME = {FILEBUF_LITERAL(CHAIN, FLAGS, FD), STD_VTABLE} + +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); + +#ifdef _STDIO_USES_IOSTREAM +_IO_FILE *_IO_list_all = &_IO_stderr_.file; +#else /* !_STDIO_USES_IOSTREAM */ +#include "stdiostream.h" + +struct _IO_fake_stdiobuf { + struct { + _IO_FILE file; + const void *vtable; + } s; + FILE *stdio_file; +}; + +/* Define stdiobuf_vtable as a name for the virtual function table + of the stdiobuf class. */ +#ifndef stdiobuf_vtable +#ifdef __GNUC__ +extern struct _IO_jump_t stdiobuf_vtable + asm (_G_VTABLE_LABEL_PREFIX +#if _G_VTABLE_LABEL_HAS_LENGTH + "8" +#endif + "stdiobuf"); +#else /* !__GNUC__ */ +#if _G_VTABLE_LABEL_HAS_LENGTH +#define stdiobuf_vtable _G_VTABLE_LABEL_PREFIX_ID##8stdiobuf +#else +#define stdiobuf_vtable _G_VTABLE_LABEL_PREFIX_ID##stdiobuf +#endif +extern struct _IO_jump_t stdiobuf_vtable; +#endif /* !__GNUC__ */ +#endif /* !stdiobuf_vtable */ + +#if _IO_UNIFIED_JUMPTABLES +#define JUMP_PTR /* Nothing */ +#else +#define JUMP_PTR &_IO_streambuf_jumps, +#endif + +#define DEF_STDIOFILE(NAME, FD, FILE, FLAGS, CHAIN) \ + struct _IO_fake_stdiobuf NAME = \ + {{{ _IO_MAGIC+_IO_LINKED+_IO_IS_FILEBUF+_IO_UNBUFFERED+FLAGS, \ + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, CHAIN, JUMP_PTR FD},\ + &stdiobuf_vtable}, FILE} + +DEF_STDIOFILE(_IO_stdin_buf, 0, stdin, _IO_NO_WRITES, &_IO_stderr_.file); +DEF_STDIOFILE(_IO_stdout_buf, 1, stdout, _IO_NO_READS, &_IO_stdin_buf.s.file); +DEF_STDIOFILE(_IO_stderr_buf, 2, stderr, _IO_NO_READS, &_IO_stdout_buf.s.file); + +_IO_FILE *_IO_list_all = &_IO_stderr_buf.s.file; +#endif /* !_STDIO_USES_IOSTREAM */ diff --git a/gnu/lib/libg++/libio/stdstreams.cc b/gnu/lib/libg++/libio/stdstreams.cc new file mode 100644 index 00000000000..051ca574fc8 --- /dev/null +++ b/gnu/lib/libg++/libio/stdstreams.cc @@ -0,0 +1,149 @@ +/* This is part of libio/iostream, providing -*- C++ -*- input/output. +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. */ + +/* Written by Per Bothner (bothner@cygnus.com). */ + +#include "libioP.h" +#include "streambuf.h" +#include <stdio.h> + +// The ANSI draft requires that operations on cin/cout/cerr can be +// mixed with operations on stdin/stdout/stderr on a character by +// character basis. This normally requires that the streambuf's +// used by cin/cout/cerr be stdiostreams. However, if the stdio +// implementation is the one that is built using this library, +// then we don't need to, since in that case stdin/stdout/stderr +// are identical to _IO_stdin/_IO_stdout/_IO_stderr. + +#include "libio.h" + +#ifdef _STDIO_USES_IOSTREAM +#define CIN_SBUF _IO_stdin_ +#define COUT_SBUF _IO_stdout_ +#define CERR_SBUF _IO_stderr_ +static int use_stdiobuf = 0; +#else +#define CIN_SBUF _IO_stdin_buf +#define COUT_SBUF _IO_stdout_buf +#define CERR_SBUF _IO_stderr_buf +static int use_stdiobuf = 1; +#endif + +#define cin CIN +#define cout COUT +#define cerr CERR +#define clog CLOG +#include "iostream.h" +#undef cin +#undef cout +#undef cerr +#undef clog + +#ifdef __GNUG__ +#define PAD 0 /* g++ allows 0-length arrays. */ +#else +#define PAD 1 +#endif +struct _fake_istream { + struct myfields { +#ifdef __GNUC__ + _ios_fields *vb; /* pointer to virtual base class ios */ + _IO_ssize_t _gcount; +#else + /* This is supposedly correct for cfront. */ + _IO_ssize_t _gcount; + void *vptr; + _ios_fields *vb; /* pointer to virtual base class ios */ +#endif + } mine; + _ios_fields base; + char filler[sizeof(struct istream)-sizeof(struct _ios_fields)+PAD]; +}; +struct _fake_ostream { + struct myfields { +#ifndef __GNUC__ + void *vptr; +#endif + _ios_fields *vb; /* pointer to virtual base class ios */ + } mine; + _ios_fields base; + char filler[sizeof(struct ostream)-sizeof(struct _ios_fields)+PAD]; +}; + + +#ifdef _IO_NEW_STREAMS +#define STD_STR(SBUF, TIE, EXTRA_FLAGS) \ + (streambuf*)&SBUF, TIE, 0, ios::skipws|ios::dec|EXTRA_FLAGS, ' ',0,0,6 +#else +#define STD_STR(SBUF, TIE, EXTRA_FLAGS) \ + (streambuf*)&SBUF, TIE, 0, ios::dont_close|ios::dec|ios::skipws|EXTRA_FLAGS, ' ',0,0,6 +#endif + +#ifdef __GNUC__ +#define OSTREAM_DEF(NAME, SBUF, TIE, EXTRA_FLAGS) \ + _fake_ostream NAME = { {&NAME.base}, {STD_STR(SBUF, TIE, EXTRA_FLAGS) }}; +#define ISTREAM_DEF(NAME, SBUF, TIE, EXTRA_FLAGS) \ + _fake_istream NAME = { {&NAME.base}, {STD_STR(SBUF, TIE, EXTRA_FLAGS) }}; +#else +#define OSTREAM_DEF(NAME, SBUF, TIE, EXTRA_FLAGS) \ + _fake_ostream NAME = { {0, &NAME.base}, {STD_STR(SBUF, TIE, EXTRA_FLAGS) }}; +#define ISTREAM_DEF(NAME, SBUF, TIE, EXTRA_FLAGS) \ + _fake_istream NAME = {{0, 0, &NAME.base}, {STD_STR(SBUF, TIE, EXTRA_FLAGS)}}; +#endif + +OSTREAM_DEF(cout, COUT_SBUF, NULL, 0) +OSTREAM_DEF(cerr, CERR_SBUF,(ostream*)&cout, ios::unitbuf) +ISTREAM_DEF(cin, CIN_SBUF, (ostream*)&cout, 0) + +/* Only for (partial) compatibility with AT&T's library. */ +OSTREAM_DEF(clog, CERR_SBUF, (ostream*)&cout, 0) + +// Switches between using _IO_std{in,out,err} and __std{in,out,err}_buf +// for standard streams. This does not normally need to be called +// explicitly, but is provided for AT&T compatibility. + +int ios::sync_with_stdio(int new_state) +{ +#ifdef _STDIO_USES_IOSTREAM + // It is always synced. + return 0; +#else + if (new_state == use_stdiobuf) // The usual case now. + return use_stdiobuf; + if (new_state) { + cin.base._strbuf = (streambuf*)&_IO_stdin_buf; + cout.base._strbuf = (streambuf*)&_IO_stdout_buf; + cerr.base._strbuf = (streambuf*)&_IO_stderr_buf; + clog.base._strbuf = (streambuf*)&_IO_stderr_buf; + } else { + cin.base._strbuf = (streambuf*)_IO_stdin; + cout.base._strbuf = (streambuf*)_IO_stdout; + cerr.base._strbuf = (streambuf*)_IO_stderr; + clog.base._strbuf = (streambuf*)_IO_stderr; + } + int old_state = use_stdiobuf; + use_stdiobuf = new_state; + return old_state; +#endif +} diff --git a/gnu/lib/libg++/libio/stream.cc b/gnu/lib/libg++/libio/stream.cc new file mode 100644 index 00000000000..db57bb47643 --- /dev/null +++ b/gnu/lib/libg++/libio/stream.cc @@ -0,0 +1,144 @@ +/* +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 <stdarg.h> +#include "libioP.h" +#include "stream.h" +#include "strstream.h" + +static char Buffer[_IO_BUFSIZ]; +#define EndBuffer (Buffer+_IO_BUFSIZ) +static char* next_chunk = Buffer; // Start of available part of Buffer. + +char* form(const char* format, ...) +{ + int space_left = EndBuffer - next_chunk; + // If less that 25% of the space is available start over. + if (space_left < (_IO_BUFSIZ>>2)) + next_chunk = Buffer; + char* buf = next_chunk; + + strstreambuf stream(buf, EndBuffer-buf-1, buf); + va_list ap; + va_start(ap, format); + int count = stream.vform(format, ap); + va_end(ap); + stream.sputc(0); + next_chunk = buf + stream.pcount(); + return buf; +} + +#define u_long unsigned long + +static char* itoa(unsigned long i, int size, int neg, int base) +{ + // Conservative estimate: If base==2, might need 8 characters + // for each input byte, but normally 3 is plenty. + int needed = size ? size + : (base >= 8 ? 3 : 8) * sizeof(unsigned long) + 2; + int space_left = EndBuffer - next_chunk; + if (space_left <= needed) + next_chunk = Buffer; // start over. + + char* buf = next_chunk; + + register char* ptr = buf+needed+1; + next_chunk = ptr; + + if (needed < (2+neg) || ptr > EndBuffer) + return NULL; + *--ptr = 0; + + if (i == 0) + *--ptr = '0'; + while (i != 0 && ptr > buf) { + int ch = i % base; + i = i / base; + if (ch >= 10) + ch += 'a' - 10; + else + ch += '0'; + *--ptr = ch; + } + if (neg) + *--ptr = '-'; + if (size == 0) + return ptr; + while (ptr > buf) + *--ptr = ' '; + return buf; +} + +char* dec(long i, int len /* = 0 */) +{ + if (i >= 0) return itoa((unsigned long)i, len, 0, 10); + else return itoa((unsigned long)(-i), len, 1, 10); +} +char* dec(int i, int len /* = 0 */) +{ + if (i >= 0) return itoa((unsigned long)i, len, 0, 10); + else return itoa((unsigned long)(-i), len, 1, 10); +} +char* dec(unsigned long i, int len /* = 0 */) +{ + return itoa(i, len, 0, 10); +} +char* dec(unsigned int i, int len /* = 0 */) +{ + return itoa(i, len, 0, 10); +} + +char* hex(long i, int len /* = 0 */) +{ + return itoa((unsigned long)i, len, 0, 16); +} +char* hex(int i, int len /* = 0 */) +{ + return itoa((unsigned long)i, len, 0, 16); +} +char* hex(unsigned long i, int len /* = 0 */) +{ + return itoa(i, len, 0, 16); +} +char* hex(unsigned int i, int len /* = 0 */) +{ + return itoa(i, len, 0, 16); +} + +char* oct(long i, int len /* = 0 */) +{ + return itoa((unsigned long)i, len, 0, 8); +} +char* oct(int i, int len /* = 0 */) +{ + return itoa((unsigned long)i, len, 0, 8); +} +char* oct(unsigned long i, int len /* = 0 */) +{ + return itoa(i, len, 0, 8); +} +char* oct(unsigned int i, int len /* = 0 */) +{ + return itoa(i, len, 0, 8); +} diff --git a/gnu/lib/libg++/libio/stream.h b/gnu/lib/libg++/libio/stream.h new file mode 100644 index 00000000000..2a791dffebe --- /dev/null +++ b/gnu/lib/libg++/libio/stream.h @@ -0,0 +1,57 @@ +/* +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. */ + +#ifndef _COMPAT_STREAM_H +#define _COMPAT_STREAM_H + +// Compatibility with old library. + +#define _STREAM_COMPAT +#include <iostream.h> + +extern "C++" { +extern char* form(const char*, ...); + +extern char* dec(long, int=0); +extern char* dec(int, int=0); +extern char* dec(unsigned long, int=0); +extern char* dec(unsigned int, int=0); + +extern char* hex(long, int=0); +extern char* hex(int, int=0); +extern char* hex(unsigned long, int=0); +extern char* hex(unsigned int, int=0); + +extern char* oct(long, int=0); +extern char* oct(int, int=0); +extern char* oct(unsigned long, int=0); +extern char* oct(unsigned int, int=0); + +char* chr(char ch, int width = 0); +char* str(const char* s, int width = 0); + +inline istream& WS(istream& str) { return ws(str); } +} // extern "C++" + +#endif /* !_COMPAT_STREAM_H */ diff --git a/gnu/lib/libg++/libio/streambuf.cc b/gnu/lib/libg++/libio/streambuf.cc new file mode 100644 index 00000000000..d66af097aa5 --- /dev/null +++ b/gnu/lib/libg++/libio/streambuf.cc @@ -0,0 +1,343 @@ +/* This is part of libio/iostream, providing -*- C++ -*- input/output. +Copyright (C) 1991, 1992, 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 _STREAM_COMPAT +#ifdef __GNUG__ +#pragma implementation +#endif +#include "iostreamP.h" +#include <string.h> +#include <stdarg.h> +#include <errno.h> +#ifndef errno +extern int errno; +#endif + +void streambuf::_un_link() { _IO_un_link(this); } + +void streambuf::_link_in() { _IO_link_in(this); } + +int streambuf::switch_to_get_mode() +{ return _IO_switch_to_get_mode(this); } + +void streambuf::free_backup_area() +{ _IO_free_backup_area(this); } + +#if 0 +int streambuf::switch_to_put_mode() +{ return _IO_:switch_to_put_mode(this); } +#endif + +int __overflow(streambuf* sb, int c) +{ + return sb->overflow(c); +} + +int streambuf::underflow() +{ return EOF; } + +int streambuf::uflow() +{ return _IO_default_uflow (this); } + +int streambuf::overflow(int /* = EOF */) +{ return EOF; } + +streamsize streambuf::xsputn(register const char* s, streamsize n) +{ return _IO_default_xsputn(this, s, n); } + +streamsize streambuf::xsgetn(char* s, streamsize n) +{ return _IO_default_xsgetn(this, s, n); } + +int streambuf::ignore(int n) +{ + register int more = n; + for (;;) { + int count = _IO_read_end - _IO_read_ptr; // Data available. + if (count > 0) { + if (count > more) + count = more; + _IO_read_ptr += count; + more -= count; + } + if (more == 0 || __underflow(this) == EOF) + break; + } + return n - more; +} + +int streambuf::sync() +{ + return 0; +} + +int streambuf::pbackfail(int c) +{ + return _IO_default_pbackfail(this, c); +} + +streambuf* streambuf::setbuf(char* p, int len) +{ + if (sync() == EOF) + return NULL; + if (p == NULL || len == 0) { + unbuffered(1); + setb(_shortbuf, _shortbuf+1, 0); + } + else { + unbuffered(0); + setb(p, p+len, 0); + } + setp(0, 0); + setg(0, 0, 0); + return this; +} + +streampos streambuf::seekpos(streampos pos, int mode) +{ + return seekoff(pos, ios::beg, mode); +} + +streampos streambuf::sseekpos(streampos pos, int mode) +{ + return _IO_seekpos (this, pos, mode); +} + +void streambuf::setb(char* b, char* eb, int a) +{ _IO_setb(this, b, eb, a); } + +int streambuf::doallocate() { return _IO_default_doallocate(this); } + +void streambuf::doallocbuf() { _IO_doallocbuf(this); } + +#if !_IO_UNIFIED_JUMPTABLES +/* The following are jump table entries that just call the virtual method */ + +static int _IO_sb_overflow(_IO_FILE *fp, int c) +{ return ((streambuf*)fp)->overflow(c); } +static int _IO_sb_underflow(_IO_FILE *fp) +{ return ((streambuf*)fp)->underflow(); } +static _IO_size_t _IO_sb_xsputn(_IO_FILE *fp, const void *s, _IO_size_t n) +{ return ((streambuf*)fp)->xsputn((const char*)s, n); } +static _IO_size_t _IO_sb_xsgetn(_IO_FILE *fp, void *s, _IO_size_t n) +{ return ((streambuf*)fp)->xsgetn((char*)s, n); } +static int _IO_sb_close(_IO_FILE *fp) +{ return ((streambuf*)fp)->sys_close(); } +static int _IO_sb_stat(_IO_FILE *fp, void *b) +{ return ((streambuf*)fp)->sys_stat(b); } +static int _IO_sb_doallocate(_IO_FILE *fp) +{ return ((streambuf*)fp)->doallocate(); } + +static _IO_pos_t _IO_sb_seekoff(_IO_FILE *fp, _IO_off_t pos, int dir, int mode) +{ + return ((streambuf*)fp)->seekoff(pos, (ios::seek_dir)dir, mode); +} + +static _IO_pos_t _IO_sb_seekpos(_IO_FILE *fp, _IO_pos_t pos, int mode) +{ + return ((streambuf*)fp)->seekpos(pos, mode); +} + +static int _IO_sb_pbackfail(_IO_FILE *fp, int ch) +{ return ((streambuf*)fp)->pbackfail(ch); } +static void _IO_sb_finish(_IO_FILE *fp) +{ ((streambuf*)fp)->~streambuf(); } +static _IO_ssize_t _IO_sb_read(_IO_FILE *fp, void *buf, _IO_ssize_t n) +{ return ((streambuf*)fp)->sys_read((char*)buf, n); } +static _IO_ssize_t _IO_sb_write(_IO_FILE *fp, const void *buf, _IO_ssize_t n) +{ return ((streambuf*)fp)->sys_write((const char*)buf, n); } +static int _IO_sb_sync(_IO_FILE *fp) +{ return ((streambuf*)fp)->sync(); } +static _IO_pos_t _IO_sb_seek(_IO_FILE *fp, _IO_off_t off, int dir) +{ return ((streambuf*)fp)->sys_seek(off, (_seek_dir)dir); } +static _IO_FILE* _IO_sb_setbuf(_IO_FILE *fp, char *buf, _IO_ssize_t n) +{ return ((streambuf*)fp)->setbuf(buf, n); } + +/* This callbacks in this jumptable just call the corresponding + virtual function, so that C functions can access (potentially user-defined) + streambuf-derived objects. + Contrast the builtinbuf class, which does the converse: Allow + C++ virtual calls to to be used on _IO_FILE objects that are builtin + (or defined by C code). */ + + +struct _IO_jump_t _IO_streambuf_jumps = { + JUMP_INIT_DUMMY, + JUMP_INIT(finish, _IO_sb_finish), + JUMP_INIT(overflow, _IO_sb_overflow), + JUMP_INIT(underflow, _IO_sb_underflow), + JUMP_INIT(uflow, _IO_default_uflow), + JUMP_INIT(pbackfail, _IO_sb_pbackfail), + JUMP_INIT(xsputn, _IO_sb_xsputn), + JUMP_INIT(xsgetn, _IO_sb_xsgetn), + JUMP_INIT(seekoff, _IO_sb_seekoff), + JUMP_INIT(seekpos, _IO_sb_seekpos), + JUMP_INIT(setbuf, _IO_sb_setbuf), + JUMP_INIT(sync, _IO_sb_sync), + JUMP_INIT(doallocate, _IO_sb_doallocate), + JUMP_INIT(read, _IO_sb_read), + JUMP_INIT(write, _IO_sb_write), + JUMP_INIT(seek, _IO_sb_seek), + JUMP_INIT(close, _IO_sb_close), + JUMP_INIT(stat, _IO_sb_stat) +}; +#endif + +streambuf::streambuf(int flags) +{ + _IO_init(this, flags); +#if !_IO_UNIFIED_JUMPTABLES + _jumps = &_IO_streambuf_jumps; +#endif +} + +streambuf::~streambuf() { _IO_default_finish(this); } + +streampos +streambuf::seekoff(streamoff, _seek_dir, int /*=ios::in|ios::out*/) +{ + return EOF; +} + +streampos +streambuf::sseekoff(streamoff o , _seek_dir d, int m /*=ios::in|ios::out*/) +{ + return _IO_seekoff (this, o, d, m); +} + +int streambuf::sputbackc(char c) +{ + return _IO_sputbackc(this, c); +} + +int streambuf::sungetc() +{ + return _IO_sungetc(this); +} + +#if 0 /* Work in progress */ +void streambuf::collumn(int c) +{ + if (c == -1) + _collumn = -1; + else + _collumn = c - (_IO_write_ptr - _IO_write_base); +} +#endif + + +int streambuf::get_column() +{ + if (_cur_column) + return _IO_adjust_column(_cur_column - 1, pbase(), pptr() - pbase()); + return -1; +} + +int streambuf::set_column(int i) +{ + _cur_column = i+1; + return 0; +} + +int streambuf::flush_all() { return _IO_flush_all (); } + +void streambuf::flush_all_linebuffered() +{ _IO_flush_all_linebuffered(); } + +int streambuf::sys_stat(void *) +{ +#ifdef EIO + errno = EIO; +#endif + return -1; +} + +streamsize streambuf::sys_read(char* /*buf*/, streamsize /*size*/) +{ + return 0; +} + +streamsize streambuf::sys_write(const char* /*buf*/, streamsize /*size*/) +{ + return 0; +} + +streampos streambuf::sys_seek(streamoff, _seek_dir) +{ + return EOF; +} + +int streambuf::sys_close() { return 0; /* Suceess; do nothing */ } + +streammarker::streammarker(streambuf *sb) +{ + _IO_init_marker(this, sb); +} + +streammarker::~streammarker() +{ + _IO_remove_marker(this); +} + +#define BAD_DELTA EOF + +int streammarker::delta(streammarker& other_mark) +{ + return _IO_marker_difference(this, &other_mark); +} + +int streammarker::delta() +{ + return _IO_marker_delta(this); +} + +int streambuf::seekmark(streammarker& mark, int delta /* = 0 */) +{ + return _IO_seekmark(this, &mark, delta); +} + +void streambuf::unsave_markers() +{ + _IO_unsave_markers(this); +} + +int ios::readable() { return !(rdbuf()->_flags & _IO_NO_READS); } +int ios::writable() { return !(rdbuf()->_flags & _IO_NO_WRITES); } +int ios::is_open() { return rdbuf() + && (rdbuf()->_flags & _IO_NO_READS+_IO_NO_WRITES) + != _IO_NO_READS+_IO_NO_WRITES; } + +#if defined(linux) +#define IO_CLEANUP +#endif + +#ifdef IO_CLEANUP + IO_CLEANUP +#else +struct __io_defs { + ~__io_defs() { _IO_cleanup (); } +}; +__io_defs io_defs__; +#endif diff --git a/gnu/lib/libg++/libio/streambuf.h b/gnu/lib/libg++/libio/streambuf.h new file mode 100644 index 00000000000..9eab279759c --- /dev/null +++ b/gnu/lib/libg++/libio/streambuf.h @@ -0,0 +1,473 @@ +/* This is part of libio/iostream, providing -*- C++ -*- input/output. +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. */ + +#ifndef _STREAMBUF_H +#define _STREAMBUF_H +#ifdef __GNUG__ +#pragma interface +#endif + +/* #define _G_IO_THROW */ /* Not implemented: ios::failure */ + +#define _IO_NEW_STREAMS // new optimizated stream representation + +extern "C" { +#include <libio.h> +} +//#include <_G_config.h> +#ifdef _IO_NEED_STDARG_H +#include <stdarg.h> +#endif +#ifndef _IO_va_list +#define _IO_va_list char * +#endif + +#ifndef EOF +#define EOF (-1) +#endif +#ifndef NULL +#ifdef __GNUC__ +#define NULL ((void*)0) +#else +#define NULL (0) +#endif +#endif + +#ifndef _IO_wchar_t +#define _IO_wchar_t short +#endif + +extern "C++" { +class istream; /* Work-around for a g++ name mangling bug. Fixed in 2.6. */ +class ostream; class streambuf; + +// In case some header files defines these as macros. +#undef open +#undef close + +typedef _IO_off_t streamoff; +typedef _IO_fpos_t streampos; +typedef _IO_ssize_t streamsize; + +typedef unsigned long __fmtflags; +typedef unsigned char __iostate; + +struct _ios_fields +{ // The data members of an ios. + streambuf *_strbuf; + ostream* _tie; + int _width; + __fmtflags _flags; + _IO_wchar_t _fill; + __iostate _state; + __iostate _exceptions; + int _precision; + + void *_arrays; /* Support for ios::iword and ios::pword. */ +}; + +#define _IOS_GOOD 0 +#define _IOS_EOF 1 +#define _IOS_FAIL 2 +#define _IOS_BAD 4 + +#define _IO_INPUT 1 +#define _IO_OUTPUT 2 +#define _IO_ATEND 4 +#define _IO_APPEND 8 +#define _IO_TRUNC 16 +#define _IO_NOCREATE 32 +#define _IO_NOREPLACE 64 +#define _IO_BIN 128 + +#ifdef _STREAM_COMPAT +enum state_value { + _good = _IOS_GOOD, + _eof = _IOS_EOF, + _fail = _IOS_FAIL, + _bad = _IOS_BAD }; +enum open_mode { + input = _IO_INPUT, + output = _IO_OUTPUT, + atend = _IO_ATEND, + append = _IO_APPEND }; +#endif + +class ios : public _ios_fields { + ios& operator=(ios&); /* Not allowed! */ + public: + typedef __fmtflags fmtflags; + typedef int iostate; + typedef int openmode; + typedef int streamsize; + enum io_state { + goodbit = _IOS_GOOD, + eofbit = _IOS_EOF, + failbit = _IOS_FAIL, + badbit = _IOS_BAD }; + enum open_mode { + in = _IO_INPUT, + out = _IO_OUTPUT, + ate = _IO_ATEND, + app = _IO_APPEND, + trunc = _IO_TRUNC, + nocreate = _IO_NOCREATE, + noreplace = _IO_NOREPLACE, + bin = _IOS_BIN }; + enum seek_dir { beg, cur, end}; + // ANSI: typedef enum seek_dir seekdir; etc + // NOTE: If adding flags here, before to update ios::bitalloc(). + enum { skipws=_IO_SKIPWS, + left=_IO_LEFT, right=_IO_RIGHT, internal=_IO_INTERNAL, + dec=_IO_DEC, oct=_IO_OCT, hex=_IO_HEX, + showbase=_IO_SHOWBASE, showpoint=_IO_SHOWPOINT, + uppercase=_IO_UPPERCASE, showpos=_IO_SHOWPOS, + scientific=_IO_SCIENTIFIC, fixed=_IO_FIXED, + unitbuf=_IO_UNITBUF, stdio=_IO_STDIO +#ifndef _IO_NEW_STREAMS + , dont_close=_IO_DONT_CLOSE // Don't delete streambuf on stream destruction +#endif + }; + enum { // Masks. + basefield=dec+oct+hex, + floatfield = scientific+fixed, + adjustfield = left+right+internal + }; + +#ifdef _IO_THROW + class failure : public xmsg { + ios* _stream; + public: + failure(ios* stream) { _stream = stream; } + failure(string cause, ios* stream) { _stream = stream; } + ios* rdios() const { return _stream; } + }; +#endif + + ostream* tie() const { return _tie; } + ostream* tie(ostream* val) { ostream* save=_tie; _tie=val; return save; } + + // Methods to change the format state. + _IO_wchar_t fill() const { return (_IO_wchar_t)_fill; } + _IO_wchar_t fill(_IO_wchar_t newf) + {_IO_wchar_t oldf = (_IO_wchar_t)_fill; _fill = (char)newf; return oldf;} + fmtflags flags() const { return _flags; } + fmtflags flags(fmtflags new_val) { + fmtflags old_val = _flags; _flags = new_val; return old_val; } + int precision() const { return _precision; } + int precision(int newp) { + unsigned short oldp = _precision; _precision = (unsigned short)newp; + return oldp; } + fmtflags setf(fmtflags val) { + fmtflags oldbits = _flags; + _flags |= val; return oldbits; } + fmtflags setf(fmtflags val, fmtflags mask) { + fmtflags oldbits = _flags; + _flags = (_flags & ~mask) | (val & mask); return oldbits; } + fmtflags unsetf(fmtflags mask) { + fmtflags oldbits = _flags; + _flags &= ~mask; return oldbits; } + int width() const { return _width; } + int width(int val) { int save = _width; _width = val; return save; } + +#ifdef _IO_THROW + void _throw_failure() const { throw new ios::failure(this); } +#else + void _throw_failure() const { } +#endif + void clear(iostate state = 0) { + _state = _strbuf ? state : state|badbit; + if (_state & _exceptions) _throw_failure(); } + void set(iostate flag) { _state |= flag; + if (_state & _exceptions) _throw_failure(); } + void setstate(iostate flag) { _state |= flag; // ANSI + if (_state & _exceptions) _throw_failure(); } + int good() const { return _state == 0; } + int eof() const { return _state & ios::eofbit; } + int fail() const { return _state & (ios::badbit|ios::failbit); } + int bad() const { return _state & ios::badbit; } + iostate rdstate() const { return _state; } + operator void*() const { return fail() ? (void*)0 : (void*)(-1); } + int operator!() const { return fail(); } + iostate exceptions() const { return _exceptions; } + void exceptions(iostate enable) { + _exceptions = enable; + if (_state & _exceptions) _throw_failure(); } + + streambuf* rdbuf() const { return _strbuf; } + streambuf* rdbuf(streambuf *_s) { + streambuf *_old = _strbuf; _strbuf = _s; clear (); return _old; } + + static int sync_with_stdio(int on); + static void sync_with_stdio() { sync_with_stdio(1); } + static fmtflags bitalloc(); + static int xalloc(); + void*& pword(int); + void* pword(int) const; + long& iword(int); + long iword(int) const; + +#ifdef _STREAM_COMPAT + void unset(state_value flag) { _state &= ~flag; } + void close(); + int is_open(); + int readable(); + int writable(); +#endif + + // Used to initialize standard streams. Not needed in this implementation. + class Init { + public: + Init () { } + }; + + protected: + inline ios(streambuf* sb = 0, ostream* tie_to = 0); + inline virtual ~ios(); + inline void init(streambuf* sb, ostream* tie = 0); +}; + +#if __GNUG__==1 +typedef int _seek_dir; +#else +typedef ios::seek_dir _seek_dir; +#endif + +// 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. + +// A streammarker remembers a position in a buffer. +// You are guaranteed to be able to seek back to it if it is saving(). +class streammarker : private _IO_marker { + friend class streambuf; + void set_offset(int offset) { _pos = offset; } + public: + streammarker(streambuf *sb); + ~streammarker(); + int saving() { return 1; } + int delta(streammarker&); + int delta(); +}; + +struct streambuf : public _IO_FILE { // protected?? + friend class ios; + friend class istream; + friend class ostream; + friend class streammarker; + const void *&_vtable() { return *(const void**)((_IO_FILE*)this + 1); } + protected: + static streambuf* _list_all; /* List of open streambufs. */ + _IO_FILE*& xchain() { return _chain; } + void _un_link(); + void _link_in(); + char* gptr() const + { return _IO_file_flags & _IO_IN_BACKUP ? _IO_save_base : _IO_read_ptr; } + char* pptr() const { return _IO_write_ptr; } + char* egptr() const + { return _IO_file_flags & _IO_IN_BACKUP ? _IO_save_end : _IO_read_end; } + char* epptr() const { return _IO_write_end; } + char* pbase() const { return _IO_write_base; } + char* eback() const + { return _IO_file_flags & _IO_IN_BACKUP ? _IO_save_base : _IO_read_base;} + char* base() const { return _IO_buf_base; } + char* ebuf() const { return _IO_buf_end; } + int blen() const { return _IO_buf_end - _IO_buf_base; } + void xput_char(char c) { *_IO_write_ptr++ = c; } + int xflags() { return _IO_file_flags; } + int xflags(int f) {int fl = _IO_file_flags; _IO_file_flags = f; return fl;} + void xsetflags(int f) { _IO_file_flags |= f; } + void xsetflags(int f, int mask) + { _IO_file_flags = (_IO_file_flags & ~mask) | (f & mask); } + void gbump(int n) + { _IO_file_flags & _IO_IN_BACKUP ? (_IO_save_base+=n):(_IO_read_ptr+=n);} + void pbump(int n) { _IO_write_ptr += n; } + void setb(char* b, char* eb, int a=0); + void setp(char* p, char* ep) + { _IO_write_base=_IO_write_ptr=p; _IO_write_end=ep; } + void setg(char* eb, char* g, char *eg) { + if (_IO_file_flags & _IO_IN_BACKUP) _IO_free_backup_area(this); + _IO_read_base = eb; _IO_read_ptr = g; _IO_read_end = eg; } + char *shortbuf() { return _shortbuf; } + + int in_backup() { return _flags & _IO_IN_BACKUP; } + // The start of the main get area: FIXME: wrong for write-mode filebuf? + char *Gbase() { return in_backup() ? _IO_save_base : _IO_read_base; } + // The end of the main get area: + char *eGptr() { return in_backup() ? _IO_save_end : _IO_read_end; } + // The start of the backup area: + char *Bbase() { return in_backup() ? _IO_read_base : _IO_save_base; } + char *Bptr() { return _IO_backup_base; } + // The end of the backup area: + char *eBptr() { return in_backup() ? _IO_read_end : _IO_save_end; } + char *Nbase() { return _IO_save_base; } + char *eNptr() { return _IO_save_end; } + int have_backup() { return _IO_save_base != NULL; } + int have_markers() { return _markers != NULL; } + void free_backup_area(); + void unsave_markers(); // Make all streammarkers !saving(). + int put_mode() { return _flags & _IO_CURRENTLY_PUTTING; } + int switch_to_get_mode(); + + streambuf(int flags=0); + public: + static int flush_all(); + static void flush_all_linebuffered(); // Flush all line buffered files. + virtual ~streambuf(); + virtual int overflow(int c = EOF); // Leave public for now + virtual int underflow(); // Leave public for now + virtual int uflow(); // Leave public for now + virtual int pbackfail(int c); +// virtual int showmany (); + virtual streamsize xsputn(const char* s, streamsize n); + virtual streamsize xsgetn(char* s, streamsize n); + virtual streampos seekoff(streamoff, _seek_dir, int mode=ios::in|ios::out); + virtual streampos seekpos(streampos pos, int mode = ios::in|ios::out); + + streampos pubseekoff(streamoff o, _seek_dir d, int mode=ios::in|ios::out) + { return _IO_seekoff (this, o, d, mode); } + streampos pubseekpos(streampos pos, int mode = ios::in|ios::out) + { return _IO_seekpos (this, pos, mode); } + streampos sseekoff(streamoff, _seek_dir, int mode=ios::in|ios::out); + streampos sseekpos(streampos pos, int mode = ios::in|ios::out); + virtual streambuf* setbuf(char* p, int len); + virtual int sync(); + virtual int doallocate(); + + int seekmark(streammarker& mark, int delta = 0); + int sputbackc(char c); + int sungetc(); + int unbuffered() { return _flags & _IO_UNBUFFERED ? 1 : 0; } + int linebuffered() { return _flags & _IO_LINE_BUF ? 1 : 0; } + void unbuffered(int i) + { if (i) _flags |= _IO_UNBUFFERED; else _flags &= ~_IO_UNBUFFERED; } + void linebuffered(int i) + { if (i) _flags |= _IO_LINE_BUF; else _flags &= ~_IO_LINE_BUF; } + int allocate() { // For AT&T compatibility + if (base() || unbuffered()) return 0; + else return doallocate(); } + // Allocate a buffer if needed; use _shortbuf if appropriate. + void allocbuf() { if (base() == NULL) doallocbuf(); } + void doallocbuf(); + int in_avail() { return _IO_read_end - _IO_read_ptr; } + int out_waiting() { return _IO_write_ptr - _IO_write_base; } + streamsize sputn(const char* s, streamsize n) { return xsputn(s, n); } + streamsize padn(char pad, streamsize n) { return _IO_padn(this, pad, n); } + streamsize sgetn(char* s, streamsize n) { return _IO_sgetn(this, s, n); } + int ignore(int); + int get_column(); + int set_column(int); + long sgetline(char* buf, _IO_size_t n, char delim, int putback_delim); + int sputc(int c) { return _IO_putc(c, this); } + int sbumpc() { return _IO_getc(this); } + int sgetc() { return _IO_peekc(this); } + int snextc() { + if (_IO_read_ptr >= _IO_read_end && __underflow(this) == EOF) + return EOF; + else return _IO_read_ptr++, sgetc(); } + void stossc() { if (_IO_read_ptr < _IO_read_end) _IO_read_ptr++; } + int vscan(char const *fmt0, _IO_va_list ap, ios* stream = NULL); + int scan(char const *fmt0 ...); + int vform(char const *fmt0, _IO_va_list ap); + int form(char const *fmt0 ...); +#if 0 /* Work in progress */ + int column(); // Current column number (of put pointer). -1 is unknown. + void column(int c); // Set column number of put pointer to c. +#endif + virtual streamsize sys_read(char* buf, streamsize size); + virtual streamsize sys_write(const char*, streamsize); + virtual streampos sys_seek(streamoff, _seek_dir); + virtual int sys_close(); + virtual int sys_stat(void*); // Actually, a (struct stat*) +}; + +// A backupbuf is a streambuf with full backup and savepoints on reading. +// All standard streambufs in the GNU iostream library are backupbufs. + +class filebuf : public streambuf { + protected: + void init(); + public: + static const int openprot; // Non-ANSI AT&T-ism: Default open protection. + filebuf(); + filebuf(int fd); + filebuf(int fd, char* p, int len); +#if !_IO_UNIFIED_JUMPTABLES + static filebuf *__new(); +#endif + ~filebuf(); + filebuf* attach(int fd); + filebuf* open(const char *filename, const char *mode); + filebuf* open(const char *filename, ios::openmode mode, int prot = 0664); + virtual int underflow(); + virtual int overflow(int c = EOF); + int is_open() const { return _fileno >= 0; } + int fd() const { return is_open() ? _fileno : EOF; } + filebuf* close(); + virtual int doallocate(); + virtual streampos seekoff(streamoff, _seek_dir, int mode=ios::in|ios::out); + virtual streambuf* setbuf(char* p, int len); + streamsize xsputn(const char* s, streamsize n); + streamsize xsgetn(char* s, streamsize n); + virtual int sync(); + protected: // See documentation in filebuf.C. +// virtual int pbackfail(int c); + int is_reading() { return eback() != egptr(); } + char* cur_ptr() { return is_reading() ? gptr() : pptr(); } + /* System's idea of pointer */ + char* file_ptr() { return eGptr(); } + // Low-level operations (Usually invoke system calls.) + virtual streamsize sys_read(char* buf, streamsize size); + virtual streampos sys_seek(streamoff, _seek_dir); + virtual streamsize sys_write(const char*, streamsize); + virtual int sys_stat(void*); // Actually, a (struct stat*) + virtual int sys_close(); +#if 0 + virtual uflow; + virtual showmany; +#endif +}; + +inline void ios::init(streambuf* sb, ostream* tie_to) { + _state = sb ? ios::goodbit : ios::badbit; _exceptions=0; + _strbuf=sb; _tie = tie_to; _width=0; _fill=' '; +#ifdef _IO_NEW_STREAMS + _flags=ios::skipws|ios::dec; +#else + _flags=ios::skipws|ios::dec|ios::dont_close; +#endif + _precision=6; _arrays = 0; } + +inline ios::ios(streambuf* sb, ostream* tie_to) { init(sb, tie_to); } + +inline ios::~ios() { +#ifndef _IO_NEW_STREAMS + if (!(_flags & (unsigned int)ios::dont_close)) delete rdbuf(); +#endif + if (_arrays) delete [] _arrays; +} +} // extern "C++" +#endif /* _STREAMBUF_H */ diff --git a/gnu/lib/libg++/libio/strfile.h b/gnu/lib/libg++/libio/strfile.h new file mode 100644 index 00000000000..55783bb5c1c --- /dev/null +++ b/gnu/lib/libg++/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/gnu/lib/libg++/libio/strops.c b/gnu/lib/libg++/libio/strops.c new file mode 100644 index 00000000000..f4f45259fb3 --- /dev/null +++ b/gnu/lib/libg++/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/gnu/lib/libg++/libio/strstream.cc b/gnu/lib/libg++/libio/strstream.cc new file mode 100644 index 00000000000..3e1d5a6bfa6 --- /dev/null +++ b/gnu/lib/libg++/libio/strstream.cc @@ -0,0 +1,168 @@ +/* This is part of libio/iostream, providing -*- C++ -*- input/output. +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. */ + +/* Written by Per Bothner (bothner@cygnus.com). */ + +#ifdef __GNUG__ +#pragma implementation +#endif +#include "iostreamP.h" +#include "strstream.h" +#include <string.h> + +static void* default_alloc(_IO_size_t size) +{ + return (void*)new char[size]; +} + +static void default_free(void* ptr) +{ + delete [] (char*)ptr; +} + +#if _IO_UNIFIED_JUMPTABLES +#define SET_STR_JUMPS(STRBUF) /* Nothing */ +#else +/* Set to use the _IO_str_jump jumptable, for efficiency */ + +#define SET_STR_JUMPS(STRBUF) \ + (STRBUF)->_jumps = &_IO_str_jumps,\ + (STRBUF)->_vtable() = builtinbuf_vtable; +#endif + +istrstream::istrstream(const char *cp, int n) +{ +#ifdef _IO_NEW_STREAMS + __my_sb.init_readonly (cp, n); + init (&__my_sb); +#else + init(new strstreambuf(cp, n)); + _flags &= ~ios::dont_close; +#endif + SET_STR_JUMPS(_strbuf); +} + +ostrstream::ostrstream() +{ +#ifdef _IO_NEW_STREAMS + init (&__my_sb); +#else + init(new strstreambuf()); + _flags &= ~ios::dont_close; +#endif + SET_STR_JUMPS(_strbuf); +} + +strstream::strstream() +{ +#ifdef _IO_NEW_STREAMS + init (&__my_sb); +#else + init(new strstreambuf()); + _flags &= ~ios::dont_close; +#endif + SET_STR_JUMPS(_strbuf); +} + +strstreambase::strstreambase(char *cp, int n, int mode) +#ifdef _IO_NEW_STREAMS +: __my_sb (cp, n, + (mode == ios::app || mode == ios::ate) ? cp + strlen(cp) : cp) +#endif +{ +#ifdef _IO_NEW_STREAMS + init (&__my_sb); +#else + char *pstart; + if (mode == ios::app || mode == ios::ate) + pstart = cp + strlen(cp); + else + pstart = cp; + init(new strstreambuf(cp, n, pstart)); + _flags &= ~ios::dont_close; +#endif + SET_STR_JUMPS(_strbuf); +} + +char *strstreambuf::str() +{ + freeze(1); + return base(); +} + +_IO_ssize_t strstreambuf::pcount () { return _IO_write_ptr - _IO_write_base; } + +int strstreambuf::overflow(int c /* = EOF */) +{ + return _IO_str_overflow (this, c); +} + +int strstreambuf::underflow() +{ + return _IO_str_underflow(this); +} + + +void strstreambuf::init_dynamic(_IO_alloc_type alloc, _IO_free_type free, + int initial_size) + +{ + _s._len = 0; + if (initial_size < 16) + initial_size = 16; + _s._allocate_buffer = alloc ? alloc : default_alloc; + _s._free_buffer = free ? free : default_free; + char * buf = (char*)(*_s._allocate_buffer)(initial_size); + setb(buf, buf + initial_size, 1); + setp(buf, buf + initial_size); + setg(buf, buf, buf); +} + +void strstreambuf::init_static(char *ptr, int size, char *pstart) +{ + _IO_str_init_static (this, ptr, size, pstart); +} + +void strstreambuf::init_readonly (const char *ptr, int size) +{ + _IO_str_init_readonly (this, ptr, size); +} + +strstreambuf::~strstreambuf() +{ + if (_IO_buf_base && !(_flags & _IO_USER_BUF)) + (_s._free_buffer)(_IO_buf_base); + _IO_buf_base = NULL; +} + +streampos strstreambuf::seekoff(streamoff off, _seek_dir dir, + int mode /*=ios::in|ios::out*/) +{ + return _IO_str_seekoff (this, off, dir, mode); +} + +int strstreambuf::pbackfail(int c) +{ + return _IO_str_pbackfail (this, c); +} diff --git a/gnu/lib/libg++/libio/strstream.h b/gnu/lib/libg++/libio/strstream.h new file mode 100644 index 00000000000..86a8a687587 --- /dev/null +++ b/gnu/lib/libg++/libio/strstream.h @@ -0,0 +1,123 @@ +/* This is part of libio/iostream, providing -*- C++ -*- input/output. +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. */ + +/* Written by Per Bothner (bothner@cygnus.com). */ + +#ifndef __STRSTREAM_H +#define __STRSTREAM_H +#ifdef __GNUG__ +#pragma interface +#endif +#include <iostream.h> +#include <strfile.h> + +extern "C++" { +class strstreambuf : public streambuf +{ + struct _IO_str_fields _s; + friend class istrstream; + + void init_dynamic(_IO_alloc_type alloc, _IO_free_type free, + int initial_size = 128); + void init_static(char *ptr, int size, char *pstart); + void init_readonly(const char *ptr, int size); + protected: + int is_static() const { return _s._allocate_buffer == (_IO_alloc_type)0; } + virtual int overflow(int = EOF); + virtual int underflow(); + virtual int pbackfail(int c); + public: + virtual ~strstreambuf(); + strstreambuf() { init_dynamic(0, 0); } + strstreambuf(int initial_size) { init_dynamic(0, 0, initial_size); } + strstreambuf(void *(*alloc)(_IO_size_t), void (*free)(void*)) + { init_dynamic(alloc, free); } + strstreambuf(char *ptr, int size, char *pstart = NULL) + { init_static(ptr, size, pstart); } + strstreambuf(unsigned char *ptr, int size, unsigned char *pstart = NULL) + { init_static((char*)ptr, size, (char*)pstart); } + strstreambuf(const char *ptr, int size) + { init_readonly(ptr, size); } + strstreambuf(const unsigned char *ptr, int size) + { init_readonly((const char*)ptr, size); } + strstreambuf(signed char *ptr, int size, signed char *pstart = NULL) + { init_static((char*)ptr, size, (char*)pstart); } + strstreambuf(const signed char *ptr, int size) + { init_readonly((const char*)ptr, size); } + // Note: frozen() is always true if is_static(). + int frozen() { return _flags & _IO_USER_BUF ? 1 : 0; } + void freeze(int n=1) + { if (!is_static()) + { if (n) _flags |= _IO_USER_BUF; else _flags &= ~_IO_USER_BUF; } } + _IO_ssize_t pcount(); + char *str(); + virtual streampos seekoff(streamoff, _seek_dir, int mode=ios::in|ios::out); +}; + +class strstreambase : virtual public ios { +#ifdef _IO_NEW_STREAMS + protected: + strstreambuf __my_sb; +#endif + public: +#ifdef _IO_NEW_STREAMS + strstreambuf* rdbuf() { return &__my_sb; } +#else + strstreambuf* rdbuf() { return (strstreambuf*)ios::rdbuf(); } +#endif + protected: + strstreambase() { } +#ifdef _IO_NEW_STREAMS + strstreambase(char *cp, int n); +#endif + strstreambase(char *cp, int n, int mode=ios::out); +}; + +class istrstream : public strstreambase, public istream { + public: + istrstream(const char*, int=0); +}; + +class ostrstream : public strstreambase, public ostream { + public: + ostrstream(); + ostrstream(char *cp, int n, int mode=ios::out) :strstreambase(cp,n,mode){} + _IO_ssize_t pcount() { return ((strstreambuf*)_strbuf)->pcount(); } + char *str() { return ((strstreambuf*)_strbuf)->str(); } + void freeze(int n = 1) { ((strstreambuf*)_strbuf)->freeze(n); } + int frozen() { return ((strstreambuf*)_strbuf)->frozen(); } +}; + +class strstream : public strstreambase, public iostream { + public: + strstream(); + strstream(char *cp, int n, int mode=ios::out) :strstreambase(cp,n,mode){} + _IO_ssize_t pcount() { return ((strstreambuf*)_strbuf)->pcount(); } + char *str() { return ((strstreambuf*)_strbuf)->str(); } + void freeze(int n = 1) { ((strstreambuf*)_strbuf)->freeze(n); } + int frozen() { return ((strstreambuf*)_strbuf)->frozen(); } +}; +} // extern "C++" + +#endif /*!__STRSTREAM_H*/ |
