1/* This is part of libio/iostream, providing -*- C++ -*- input/output. 2Copyright (C) 1991, 1992, 1993, 1995 Free Software Foundation 3 4This file is part of the GNU IO Library. This library is free 5software; you can redistribute it and/or modify it under the 6terms of the GNU General Public License as published by the 7Free Software Foundation; either version 2, or (at your option) 8any later version. 9 10This library is distributed in the hope that it will be useful, 11but WITHOUT ANY WARRANTY; without even the implied warranty of 12MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 13GNU General Public License for more details. 14 15You should have received a copy of the GNU General Public License 16along with this library; see the file COPYING. If not, write to the Free 17Software Foundation, 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. 18 19As a special exception, if you link this library with files 20compiled with a GNU compiler to produce an executable, this does not cause 21the resulting executable to be covered by the GNU General Public License. 22This exception does not however invalidate any other reasons why 23the executable file might be covered by the GNU General Public License. */ 24 25/* Written by Per Bothner (bothner@cygnus.com). */ 26 27#define _STREAM_COMPAT 28#ifdef __GNUG__ 29#pragma implementation 30#endif 31#include "iostreamP.h" 32#include <string.h> 33#include <stdarg.h> 34#include <errno.h> 35#ifndef errno 36extern int errno; 37#endif 38 39void streambuf::_un_link() { _IO_un_link(reinterpret_cast<_IO_FILE_plus*>(this)); } 40 41void streambuf::_link_in() { _IO_link_in(reinterpret_cast<_IO_FILE_plus*>(this)); } 42 43int streambuf::switch_to_get_mode() 44{ return _IO_switch_to_get_mode(this); } 45 46void streambuf::free_backup_area() 47{ _IO_free_backup_area(this); } 48 49#if 0 50int streambuf::switch_to_put_mode() 51{ return _IO_:switch_to_put_mode(this); } 52#endif 53 54int __overflow(streambuf* sb, int c) 55{ 56 return sb->overflow(c); 57} 58 59int streambuf::underflow() 60{ return EOF; } 61 62int streambuf::uflow() 63{ return _IO_default_uflow (this); } 64 65int streambuf::overflow(int /* = EOF */) 66{ return EOF; } 67 68streamsize streambuf::xsputn(register const char* s, streamsize n) 69{ return _IO_default_xsputn(this, s, n); } 70 71streamsize streambuf::xsgetn(char* s, streamsize n) 72{ return _IO_default_xsgetn(this, s, n); } 73 74int streambuf::ignore(int n) 75{ 76 register int more = n; 77 for (;;) { 78 int count = _IO_read_end - _IO_read_ptr; // Data available. 79 if (count > 0) { 80 if (count > more) 81 count = more; 82 _IO_read_ptr += count; 83 more -= count; 84 } 85 if (more == 0 || __underflow(this) == EOF) 86 break; 87 } 88 return n - more; 89} 90 91int streambuf::sync() 92{ 93 return 0; 94} 95 96int streambuf::pbackfail(int c) 97{ 98 return _IO_default_pbackfail(this, c); 99} 100 101streambuf* streambuf::setbuf(char* p, int len) 102{ 103 if (sync() == EOF) 104 return NULL; 105 if (p == NULL || len == 0) { 106 unbuffered(1); 107 setb(_shortbuf, _shortbuf+1, 0); 108 } 109 else { 110 unbuffered(0); 111 setb(p, p+len, 0); 112 } 113 setp(0, 0); 114 setg(0, 0, 0); 115 return this; 116} 117 118streampos streambuf::seekpos(streampos pos, int mode) 119{ 120 return seekoff(pos, ios::beg, mode); 121} 122 123streampos streambuf::sseekpos(streampos pos, int mode) 124{ 125 return _IO_seekpos (this, pos, mode); 126} 127 128void streambuf::setb(char* b, char* eb, int a) 129{ _IO_setb(this, b, eb, a); } 130 131int streambuf::doallocate() { return _IO_default_doallocate(this); } 132 133void streambuf::doallocbuf() { _IO_doallocbuf(this); } 134 135#if !_IO_UNIFIED_JUMPTABLES 136/* The following are jump table entries that just call the virtual method */ 137 138static int _IO_sb_overflow(_IO_FILE *fp, int c) 139{ return ((streambuf*)fp)->overflow(c); } 140static int _IO_sb_underflow(_IO_FILE *fp) 141{ return ((streambuf*)fp)->underflow(); } 142static _IO_size_t _IO_sb_xsputn(_IO_FILE *fp, const void *s, _IO_size_t n) 143{ return ((streambuf*)fp)->xsputn((const char*)s, n); } 144static _IO_size_t _IO_sb_xsgetn(_IO_FILE *fp, void *s, _IO_size_t n) 145{ return ((streambuf*)fp)->xsgetn((char*)s, n); } 146static int _IO_sb_close(_IO_FILE *fp) 147{ return ((streambuf*)fp)->sys_close(); } 148static int _IO_sb_stat(_IO_FILE *fp, void *b) 149{ return ((streambuf*)fp)->sys_stat(b); } 150static int _IO_sb_doallocate(_IO_FILE *fp) 151{ return ((streambuf*)fp)->doallocate(); } 152 153static _IO_pos_t _IO_sb_seekoff(_IO_FILE *fp, _IO_off_t pos, int dir, int mode) 154{ 155 return ((streambuf*)fp)->seekoff(pos, (ios::seek_dir)dir, mode); 156} 157 158static _IO_pos_t _IO_sb_seekpos(_IO_FILE *fp, _IO_pos_t pos, int mode) 159{ 160 return ((streambuf*)fp)->seekpos(pos, mode); 161} 162 163static int _IO_sb_pbackfail(_IO_FILE *fp, int ch) 164{ return ((streambuf*)fp)->pbackfail(ch); } 165static void _IO_sb_finish(_IO_FILE *fp, int) 166{ ((streambuf*)fp)->~streambuf(); } 167static _IO_ssize_t _IO_sb_read(_IO_FILE *fp, void *buf, _IO_ssize_t n) 168{ return ((streambuf*)fp)->sys_read((char*)buf, n); } 169static _IO_ssize_t _IO_sb_write(_IO_FILE *fp, const void *buf, _IO_ssize_t n) 170{ return ((streambuf*)fp)->sys_write((const char*)buf, n); } 171static int _IO_sb_sync(_IO_FILE *fp) 172{ return ((streambuf*)fp)->sync(); } 173static _IO_pos_t _IO_sb_seek(_IO_FILE *fp, _IO_off_t off, int dir) 174{ return ((streambuf*)fp)->sys_seek(off, (_seek_dir)dir); } 175static _IO_FILE* _IO_sb_setbuf(_IO_FILE *fp, char *buf, _IO_ssize_t n) 176{ return ((streambuf*)fp)->setbuf(buf, n); } 177 178/* This callbacks in this jumptable just call the corresponding 179 virtual function, so that C functions can access (potentially user-defined) 180 streambuf-derived objects. 181 Contrast the builtinbuf class, which does the converse: Allow 182 C++ virtual calls to be used on _IO_FILE objects that are builtin 183 (or defined by C code). */ 184 185 186struct _IO_jump_t _IO_streambuf_jumps = { 187 JUMP_INIT_DUMMY, 188 JUMP_INIT(finish, _IO_sb_finish), 189 JUMP_INIT(overflow, _IO_sb_overflow), 190 JUMP_INIT(underflow, _IO_sb_underflow), 191 JUMP_INIT(uflow, _IO_default_uflow), 192 JUMP_INIT(pbackfail, _IO_sb_pbackfail), 193 JUMP_INIT(xsputn, _IO_sb_xsputn), 194 JUMP_INIT(xsgetn, _IO_sb_xsgetn), 195 JUMP_INIT(seekoff, _IO_sb_seekoff), 196 JUMP_INIT(seekpos, _IO_sb_seekpos), 197 JUMP_INIT(setbuf, _IO_sb_setbuf), 198 JUMP_INIT(sync, _IO_sb_sync), 199 JUMP_INIT(doallocate, _IO_sb_doallocate), 200 JUMP_INIT(read, _IO_sb_read), 201 JUMP_INIT(write, _IO_sb_write), 202 JUMP_INIT(seek, _IO_sb_seek), 203 JUMP_INIT(close, _IO_sb_close), 204 JUMP_INIT(stat, _IO_sb_stat) 205}; 206#endif 207 208streambuf::streambuf(int flags) 209{ 210#ifdef _IO_MTSAFE_IO 211 _lock = new _IO_lock_t; 212#endif 213 _IO_init(this, flags); 214#if !_IO_UNIFIED_JUMPTABLES 215 _jumps = &_IO_streambuf_jumps; 216#endif 217} 218 219streambuf::~streambuf() 220{ 221 _IO_default_finish(this,0); 222#ifdef _IO_MTSAFE_IO 223 if (this != _IO_stdin && this != _IO_stdout && this != _IO_stderr) 224 delete _lock; 225#endif 226} 227 228streampos 229streambuf::seekoff(streamoff, _seek_dir, int /*=ios::in|ios::out*/) 230{ 231 return EOF; 232} 233 234streampos 235streambuf::sseekoff(streamoff o , _seek_dir d, int m /*=ios::in|ios::out*/) 236{ 237 return _IO_seekoff (this, o, d, m); 238} 239 240int streambuf::sputbackc(char c) 241{ 242 return _IO_sputbackc(this, c); 243} 244 245int streambuf::sungetc() 246{ 247 return _IO_sungetc(this); 248} 249 250#if 0 /* Work in progress */ 251void streambuf::collumn(int c) 252{ 253 if (c == -1) 254 _collumn = -1; 255 else 256 _collumn = c - (_IO_write_ptr - _IO_write_base); 257} 258#endif 259 260 261int streambuf::get_column() 262{ 263 if (_cur_column) 264 return _IO_adjust_column(_cur_column - 1, pbase(), pptr() - pbase()); 265 return -1; 266} 267 268int streambuf::set_column(int i) 269{ 270 _cur_column = i+1; 271 return 0; 272} 273 274int streambuf::flush_all() { return _IO_flush_all (); } 275 276void streambuf::flush_all_linebuffered() 277{ _IO_flush_all_linebuffered(); } 278 279int streambuf::sys_stat(void *) 280{ 281#ifdef EIO 282 errno = EIO; 283#endif 284 return -1; 285} 286 287streamsize streambuf::sys_read(char* /*buf*/, streamsize /*size*/) 288{ 289 return 0; 290} 291 292streamsize streambuf::sys_write(const char* /*buf*/, streamsize /*size*/) 293{ 294 return 0; 295} 296 297streampos streambuf::sys_seek(streamoff, _seek_dir) 298{ 299 return EOF; 300} 301 302int streambuf::sys_close() { return 0; /* Suceess; do nothing */ } 303 304#if _G_IO_IO_FILE_VERSION == 0x20001 305int streambuf::showmanyc() 306{ 307 return -1; 308} 309 310void streambuf::imbue(void *) 311{ 312} 313#endif 314 315streammarker::streammarker(streambuf *sb) 316{ 317 _IO_init_marker(this, sb); 318} 319 320streammarker::~streammarker() 321{ 322 _IO_remove_marker(this); 323} 324 325#define BAD_DELTA EOF 326 327int streammarker::delta(streammarker& other_mark) 328{ 329 return _IO_marker_difference(this, &other_mark); 330} 331 332int streammarker::delta() 333{ 334 return _IO_marker_delta(this); 335} 336 337int streambuf::seekmark(streammarker& mark, int delta /* = 0 */) 338{ 339 return _IO_seekmark(this, &mark, delta); 340} 341 342void streambuf::unsave_markers() 343{ 344 _IO_unsave_markers(this); 345} 346 347int ios::readable() { return !(rdbuf()->_flags & _IO_NO_READS); } 348int ios::writable() { return !(rdbuf()->_flags & _IO_NO_WRITES); } 349int ios::is_open() { return rdbuf() 350 && (rdbuf()->_flags & _IO_NO_READS+_IO_NO_WRITES) 351 != _IO_NO_READS+_IO_NO_WRITES; } 352 353#if defined(linux) 354#define IO_CLEANUP 355#endif 356 357#ifdef IO_CLEANUP 358 IO_CLEANUP 359#else 360struct __io_defs { 361 ~__io_defs() { _IO_cleanup (); } 362}; 363__io_defs io_defs__; 364#endif 365