aboutsummaryrefslogtreecommitdiff
path: root/gnu/lib/libg++/iostream/stdstreams.C
diff options
context:
space:
mode:
Diffstat (limited to 'gnu/lib/libg++/iostream/stdstreams.C')
-rw-r--r--gnu/lib/libg++/iostream/stdstreams.C145
1 files changed, 145 insertions, 0 deletions
diff --git a/gnu/lib/libg++/iostream/stdstreams.C b/gnu/lib/libg++/iostream/stdstreams.C
new file mode 100644
index 000000000000..991371a1077d
--- /dev/null
+++ b/gnu/lib/libg++/iostream/stdstreams.C
@@ -0,0 +1,145 @@
+// This is part of the iostream library, providing input/output for C++.
+// Copyright (C) 1992 Per Bothner.
+//
+// This library is free software; you can redistribute it and/or
+// modify it under the terms of the GNU Library General Public
+// License as published by the Free Software Foundation; either
+// version 2 of the License, or (at your option) any later version.
+//
+// This library is distributed in the hope that it will be useful,
+// but WITHOUT ANY WARRANTY; without even the implied warranty of
+// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+// Library General Public License for more details.
+//
+// You should have received a copy of the GNU Library General Public
+// License along with this library; if not, write to the Free
+// Software Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
+
+#include "ioprivate.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 &__std_filebuf_0/&__std_filebuf_1/&__std_filebuf_2.
+
+#ifdef _STDIO_USES_IOSTREAM
+#define USE_FILEBUF
+#endif
+
+#ifdef NAMES_HAVE_UNDERSCORE
+#define UNDERSCORE "_"
+#else
+#define UNDERSCORE ""
+#endif
+
+#ifdef USE_FILEBUF
+#define CIN_SBUF __std_filebuf_0
+#define COUT_SBUF __std_filebuf_1
+#define CERR_SBUF __std_filebuf_2
+static int use_stdiobuf = 0;
+#else
+#define CIN_SBUF __stdin_stdiobuf
+#define COUT_SBUF __stdout_stdiobuf
+#define CERR_SBUF __stderr_stdiobuf
+static int use_stdiobuf = 1;
+#endif
+
+struct _fake_filebuf;
+extern _fake_filebuf __std_filebuf_0, __std_filebuf_1, __std_filebuf_2;
+struct _fake_stdiobuf;
+extern _fake_stdiobuf __stdin_stdiobuf, __stdout_stdiobuf, __stderr_stdiobuf;
+
+#define cin CIN
+#define cout COUT
+#define cerr CERR
+#define clog CLOG
+#include "iostream.h"
+#undef cin
+#undef cout
+#undef cerr
+#undef clog
+
+#ifdef __GNUC__
+#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 */
+ _G_ssize_t _gcount;
+#else
+ /* This is supposedly correct for cfront. */
+ _G_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];
+};
+
+#define STD_STR(SBUF, TIE, EXTRA_FLAGS) \
+ (streambuf*)&SBUF, TIE, 0, ios::dont_close|ios::skipws|EXTRA_FLAGS, ' ',0,0,6
+
+#ifdef __GNUC__
+#define OSTREAM_DEF(TYPE, NAME, SBUF, TIE, EXTRA_FLAGS) \
+ TYPE NAME = { {&NAME.base}, {STD_STR(SBUF, TIE, EXTRA_FLAGS) }};
+#define ISTREAM_DEF(TYPE, NAME, SBUF, TIE, EXTRA_FLAGS) \
+ TYPE NAME = { {&NAME.base}, {STD_STR(SBUF, TIE, EXTRA_FLAGS) }};
+#else
+#define OSTREAM_DEF(TYPE, NAME, SBUF, TIE, EXTRA_FLAGS) \
+ TYPE NAME = { {0, &NAME.base}, {STD_STR(SBUF, TIE, EXTRA_FLAGS) }};
+#define ISTREAM_DEF(TYPE, NAME, SBUF, TIE, EXTRA_FLAGS) \
+ TYPE NAME = { {0, 0, &NAME.base}, {STD_STR(SBUF, TIE, EXTRA_FLAGS) }};
+#endif
+
+OSTREAM_DEF(_fake_ostream, cout, COUT_SBUF, NULL, 0)
+OSTREAM_DEF(_fake_ostream, cerr, CERR_SBUF, (ostream*)&cout, ios::unitbuf)
+ISTREAM_DEF(_fake_istream, cin, CIN_SBUF, (ostream*)&cout, 0)
+
+/* Only for (partial) compatibility with AT&T's library. */
+OSTREAM_DEF(_fake_ostream, clog, CERR_SBUF, (ostream*)&cout, 0)
+
+// Switches between using __std_filebuf_{0,1,2} and
+// __std{in,out,err}_stdiobuf for standard streams. This is
+// normally not needed, 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) {
+ cout.base._strbuf = (streambuf*)&__stdout_stdiobuf;
+ cin.base._strbuf = (streambuf*)&__stdin_stdiobuf;
+ cerr.base._strbuf = (streambuf*)&__stderr_stdiobuf;
+ clog.base._strbuf = (streambuf*)&__stderr_stdiobuf;
+ } else {
+ cout.base._strbuf = (streambuf*)&__std_filebuf_1;
+ cin.base._strbuf = (streambuf*)&__std_filebuf_0;
+ cerr.base._strbuf = (streambuf*)&__std_filebuf_2;
+ clog.base._strbuf = (streambuf*)&__std_filebuf_2;
+ }
+ int old_state = use_stdiobuf;
+ use_stdiobuf = new_state;
+ return old_state;
+#endif
+}