aboutsummaryrefslogtreecommitdiff
path: root/libio/stdstreams.cc
diff options
context:
space:
mode:
Diffstat (limited to 'libio/stdstreams.cc')
-rw-r--r--libio/stdstreams.cc153
1 files changed, 153 insertions, 0 deletions
diff --git a/libio/stdstreams.cc b/libio/stdstreams.cc
new file mode 100644
index 00000000000..a5889d738e2
--- /dev/null
+++ b/libio/stdstreams.cc
@@ -0,0 +1,153 @@
+/* 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, ASM) \
+ _fake_ostream NAME ASM = { {&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. */
+#if _G_CLOG_CONFLICT
+OSTREAM_DEF(clog, CERR_SBUF, (ostream*)&cout, 0, __asm__ ("__IO_clog"))
+#else
+OSTREAM_DEF(clog, CERR_SBUF, (ostream*)&cout, 0, )
+#endif
+
+// 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
+}