summaryrefslogtreecommitdiff
path: root/gnu/lib/libg++/iostream/stdstreams.C
blob: 991371a1077d04c0a32e143cf96abbb8e2210899 (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
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
}