/*  
**  iostream.h		C++ Runtime
**
**  Copyright (C)	Microway, Inc. 1987 - 1994.
**			P.O. BOX 79
**			Kingston, MA. 02364
**			(508) 746 - 7341 Voice
**			(508) 746 - 4678 FAX
**			e-mail tech@microway.com
**
**  This program is the property of Microway, Inc, its contents are
**  proprietary information and no part of it is to be disclosed to anyone
**  except employees of Microway, Inc., or as agreed in writing by the
**  President of Microway, Inc.
*/

#ifndef __IOSTREAM_H
# define __IOSTREAM_H

# include <stddef.h>
# ifndef EOF
#  define EOF	(-1)
# endif
# ifndef __virtual
#  ifdef __mih
#   define __virtual virtual
#  else
#   define __virtual
#  endif
# endif
# ifdef __cppv21
#  define __ios ios::
# else
#  define __ios
# endif

typedef long streamoff, streampos;

class streambuf;
class ostream;

class ios {
public:
    enum io_state { goodbit=0, eofbit, failbit, badbit=4 };
    enum open_mode { in=0x1, out=0x2, ate=0x4, app=0x8, trunc=0x10,
		     nocreate=0x20, noreplace=0x40 };
    enum seek_dir { beg=0, cur=1, end=2 };
    enum	  { skipws=0x1,
		    left=0x2, right=0x4, internal=0x8,
		    dec=0x10, oct=0x20, hex=0x40,
		    showbase=0x80, showpoint=0x100, uppercase=0x200,
		    showpos=0x400, scientific=0x800, fixed=0x1000,
		    unitbuf=0x2000, stdio=0x4000 };
    static const long basefield;
    static const long adjustfield;
    static const long floatfield;

public:
		ios(streambuf *);
   virtual	~ios();

    void	clear(int f=0)		{ _state=f;}
    int 	eof()			{ return( _state&eofbit?1:0 ); }
    int 	fail()			{ return( _state&(failbit|badbit)?1:0 ); }
    int 	good()			{ return( _state==0 ); }
    int 	bad()			{ return( _state&badbit?1:0 ); }
    int 	rdstate()		{ return( _state ); }
    long	flags() 		{ return( _flags );}
    long	flags(long f)		{ long o=_flags; _flags=f; return(o);}
    long	setf(long f)		{ long o=_flags; _flags|=f; return(o);}
    long	setf(long f, long m)	{ long o=_flags; _flags=((_flags&~m)|(f&m)); return(o);}
    long	unsetf(long f)		{ long o=_flags; _flags&=~f; return(o);}

    int 	width() 		{ return _width; }
    int 	width(int w)		{ int o=_width; _width=w; return(o);}
    int 	precision()		{ return _precision; }
    int 	precision(int p)	{ int o=_precision; _precision=p; return(o); }
    char	fill()			{ return( _fill ); }
    char	fill(char c)		{ char o=_fill; _fill=c; return(o);}

    static long bitalloc();		// I return 0 when no more bits
    static int	xalloc();
    long &	iword(int);
    void *&	pword(int);

    int 	operator!()		{ return( good()?0:1 );}
		operator void*()	{ return( good()?this:0 );}
    streambuf * rdbuf() 		{ return( _sb ); }
    ostream *	tie()			{ return _tie; }
    ostream *	tie(ostream *t) 	{ ostream *o=_tie; _tie=t; return(o); }
    static void sync_with_stdio();

protected:
		ios();
    void	init(streambuf*);

private:
    void	operator=(const ios&);	// Don't want these to happen
		ios(const ios&);	//  Declare them so compiler doesn't
					//  generate them.

protected:
    streambuf * _sb;
    int 	_flags;
    short	_width;
    short	_precision;
    char	_state;
    char	_fill;
    class ostream *_tie;
friend class Iostream_Init;
};

class streambuf {
public:
    int 	in_avail()		{ return _egptr-_gptr; }
    int 	out_waiting()		{ return _pptr-_pbase; }
   virtual streambuf *
		setbuf(char *, int);
   virtual streampos
		seekpos(streampos p, int m=ios::in|ios::out)
		{return seekoff(streamoff(p),ios::beg,m);}
   virtual streampos
		seekoff(streamoff, __ios seek_dir, int =ios::in|ios::out);
   virtual int	sync();
    int 	sbumpc()
	{ return( (_gptr>=_egptr && underflow()==EOF)?EOF:*((unsigned char *)(_gptr++)) ); }
    int 	sgetc()
	{ return (_gptr>=_egptr)?underflow():*((unsigned char *)_gptr) ; }
    int 	sgetn(char *,int);
    int 	snextc()
	{ return (++_gptr>=_egptr)?underflow():*((unsigned char *)_gptr) ; }
    int 	sputbackc(char c)
	{ return (_gptr>_eback) && !_unbuff? *--_gptr=(c&0xff): pbackfail(c); }
    int 	sputc(int ch)
	{ return (_pptr>=_epptr)? overflow(ch): ((*_pptr++ = ch)&0xff); }
    int 	sputn(const char *,int);
    void	stossc()		{ if ( _gptr<_egptr ) ++_gptr; }

public:
		streambuf();
   virtual	~streambuf();
		streambuf(char *, int);
    void	dbp();

   virtual int	pbackfail(int);
   virtual int	overflow(int =EOF);
   virtual int	underflow();

protected:
    int 	allocate()   { if ( _base!=NULL || _unbuff ) return 0; else return doallocate(); }
    int 	blen()	     { return _end-_base; }
    char *	base()	     { return _base; }
    char *	eback()      { return _eback; }
    char *	ebuf()	     { return _end; }
    char *	egptr()      { return _egptr; }
    char *	epptr()      { return _epptr; }
    char *	gptr()	     { return _gptr; }
    char *	pbase()      { return _pbase; }
    char *	pptr()	     { return _pptr; }

    void	gbump(int n) { _gptr += n; }
    void	pbump(int n) { _pptr += n; }
    void	setg(char *eb,char *g,char *eg)
			     { _eback=eb; _gptr=g; _egptr=eg; }
    void	setp(char *p,char *ep)
			     { _pbase=p; _pptr=p; _epptr=ep; }
    void	setb(char *,char *,int =0);

    int 	unbuffered() { return _unbuff; }
    void	unbuffered(int i)
			     { _unbuff=i; }
   virtual int	doallocate();

protected:
    char *_base;
    char *_end;
    char *_eback;
    char *_gptr;
    char *_egptr;
    char *_pbase;
    char *_pptr;
    char *_epptr;
    char _alloced;
    char _unbuff;
    char _tinybuffer;
private:
    void	operator=(const streambuf&);	// Don't want these to happen
		streambuf(const streambuf&);	//  So they would be defined
};

class istream : public __virtual ios {
public:
		~istream();
		istream(streambuf *);
    int 	gcount()			{ return _gcnt; }
    istream &	get(char *, int, char ='\n');
    istream &	get(unsigned char *up, int l, char d='\n')  { return get((char *) up,l,d); }
    istream &	get(char &);
    istream &	get(unsigned char &uc)		{ return get( (char &) uc ); }
    istream &	get(streambuf &, char ='\n');
    int 	get();
    istream &	getline(char *, int, char ='\n');
    istream &	getline(unsigned char *, int, char ='\n');
    istream &	ignore(int =1, int =EOF);
    int 	ipfx(int =0);
    int 	peek()				{ return( ipfx(1)?_sb->sgetc(): EOF ); }
    istream &	putback(char ch)		{ _state &= ~eofbit; if ( good()) _sb->sputbackc(ch); return *this; }
    istream &	read(char *, int);
    istream &	read(unsigned char *up, int l)	{ return read((char *)up, l); }
    istream &	seekg(streampos sp)		{ clear(); _sb->seekpos(sp,ios::in); return *this; }
    istream &	seekg(streamoff sp, seek_dir d) { clear(); _sb->seekoff(sp,d,ios::in); return *this; }
    streampos	tellg() 			{ return _sb->seekoff(0,cur,ios::in); }
    int 	sync()				{ return _sb->sync(); }

    istream &	operator>>(char *);
    istream &	operator>>(char &);
    istream &	operator>>(short &s)		{ long t; *this >> t; s=t; return *this; }
    istream &	operator>>(int &i)		{ long t; *this >> t; i=t; return *this; }
    istream &	operator>>(long &);
    istream &	operator>>(unsigned char *up)	{ return( *this >> (char *)up);}
    istream &	operator>>(unsigned char &uc)	{ return( *this >> (char &)uc);}
    istream &	operator>>(unsigned short &us)	{ return( *this >> (short &)us);}
    istream &	operator>>(unsigned int &ui)	{ return( *this >> (int &)ui);}
    istream &	operator>>(unsigned long &ul)	{ return( *this >> (long &)ul);}
    istream &	operator>>(float &f)		{ double t; *this >>t ; f=t; return *this; }
    istream &	operator>>(double &);
    istream &	operator>>(streambuf *sb);
    istream &	operator>>(istream & (*m)(istream&))	{ return m(*this); }
    istream &	operator>>(ios & (*m)(ios&))	{ m(*this); return *this; }
protected:
		istream()			{}
protected:
    int 	_gcnt;
public: 			// Added for compatability with old streams
    istream(int fd);		//  An istream based on a filebuf
    istream(int size, char *p); //  An istream based on a sting
};

class istream_wa : public istream {
public:
		istream_wa() {}
		~istream_wa();
    istream &	operator=(istream&);
    istream &	operator=(streambuf&);
};

class ostream : public __virtual ios {
public:
		~ostream();
		ostream(streambuf *);
    ostream &	seekp(streampos sp)		{ _sb->seekpos(sp,ios::out); return *this; }
    ostream &	seekp(streamoff sp, seek_dir d) { _sb->seekoff(sp,d,ios::out); return *this; }
    streampos	ftellp()			{ return _sb->seekoff(0,cur,ios::out); }
    ostream &	flush() 			{ _sb->sync(); return *this; }

    int 	opfx();
    void	osfx();

    ostream &	write(const char *, int);
    ostream &	write(const unsigned char *p, int l){ return write((const char *)p,l); }
    ostream &	put(char);

    ostream &	operator<<(const char *);
    ostream &	operator<<(const unsigned char *pt){return *this << (const char *) pt; }
    ostream &	operator<<(char c)		{ return put(c); }
    ostream &	operator<<(unsigned char c)	{ return put( char(c)); }
    ostream &	operator<<(short s)		{ return *this << long(s); }
    ostream &	operator<<(unsigned short us)	{ return *this << (unsigned long)us; }
    ostream &	operator<<(int i)		{ return *this << long(i); }
    ostream &	operator<<(unsigned int ui)	{ return *this << (unsigned long)ui; }
    ostream &	operator<<(long);
    ostream &	operator<<(unsigned long);
    ostream &	operator<<(float f)		{ return *this << double(f); }
    ostream &	operator<<(double);
    ostream &	operator<<(void *);
    ostream &	operator<<(streambuf *);
    ostream &	operator<<(ostream & (*m)(ostream&))	{ return m(*this); }
    ostream &	operator<<(ios & (*m)(ios&))	{ m(*this); return *this; }
protected:
		ostream()			{}
    void	format_number(const char *, const char *, int, int);
public: 			// Added for compatability with old streams
    ostream(int fd);		//  An ostream based on a filebuf
};

class ostream_wa : public ostream {
public:
		ostream_wa() {}
		~ostream_wa();
    ostream &	operator=(ostream&);
    ostream &	operator=(streambuf&);
};

#  ifdef __mih
class iostream : public istream, public ostream {
public:
		~iostream();
		iostream( streambuf *sb)	{ init(sb); }
protected:
		iostream() {}
};

class iostream_wa : public iostream {
public:
		iostream_wa() {}
		~iostream_wa();
    iostream &	 operator=(iostream&);
    iostream &	 operator=(streambuf&);
};
#  endif

#ifndef __NOIOSINIT
static class Iostream_Init {
    static int count;
public:
    Iostream_Init();
    ~Iostream_Init();
} __Thingamagig;
#endif


ios &dec(ios &);
ios &oct(ios &);
ios &hex(ios &);
ostream &endl(ostream &);
ostream &ends(ostream &);
ostream &flush(ostream &);
istream &ws(istream &);

# ifndef __IOSTREAM_HACK
extern istream_wa cin;
extern ostream_wa cout;
extern ostream_wa cerr;
extern ostream_wa clog;
# endif 	/* __IOSTREAM_HACK */

    /* Just for fun... */
extern char *rom(int, int w=0, int uc=1); // formatted roman numerals
			// max width=w, uc=1=>upper case, 0=>lower
extern long romtol(const char *);	  // unformat roman numerals

# undef __virtual
# undef __ios
#endif

