home *** CD-ROM | disk | FTP | other *** search
/ The Atari Compendium / The Atari Compendium (Toad Computers) (1994).iso / files / prgtools / gnustuff / tos / g__~1 / gplibs20.zoo / iostream.cc < prev    next >
Encoding:
C/C++ Source or Header  |  1993-07-13  |  16.5 KB  |  785 lines

  1. //    This is part of the iostream library, providing input/output for C++.
  2. //    Copyright (C) 1991, 1992 Per Bothner.
  3. //
  4. //    This library is free software; you can redistribute it and/or
  5. //    modify it under the terms of the GNU Library General Public
  6. //    License as published by the Free Software Foundation; either
  7. //    version 2 of the License, or (at your option) any later version.
  8. //
  9. //    This library is distributed in the hope that it will be useful,
  10. //    but WITHOUT ANY WARRANTY; without even the implied warranty of
  11. //    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
  12. //    Library General Public License for more details.
  13. //
  14. //    You should have received a copy of the GNU Library General Public
  15. //    License along with this library; if not, write to the Free
  16. //    Software Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
  17.  
  18. #ifdef __GNUG__
  19. #pragma implementation
  20. #endif
  21. #define _STREAM_COMPAT
  22. #include <ioprivat.h>
  23. #include <iostream.h>
  24. #include <stdio.h>  /* Needed for sprintf */
  25. #include <ctype.h>
  26. #include <limits.h>
  27. #include <floatio.h>
  28.  
  29. #define    BUF        (MAXEXP+MAXFRACT+1)    /* + decimal point */
  30.  
  31. //#define isspace(ch) ((ch)==' ' || (ch)=='\t' || (ch)=='\n')
  32.  
  33. istream::istream(streambuf *sb, ostream* tied) : ios(sb, tied)
  34. {
  35.     _flags |= ios::dont_close;
  36.     _gcount = 0;
  37. }
  38.  
  39. int skip_ws(streambuf* sb)
  40. {
  41.     int ch;
  42.     for (;;) {
  43.     ch = sb->sbumpc();
  44.     if (ch == EOF || !isspace(ch))
  45.         return ch;
  46.     }
  47. }
  48.  
  49. istream& istream::get(char& c)
  50. {
  51.     if (ipfx1()) {
  52.     int ch = _strbuf->sbumpc();
  53.     if (ch == EOF) {
  54.       set(ios::eofbit|ios::failbit);
  55.       _gcount = 0;
  56.     }
  57.     else {
  58.       c = (char)ch;
  59.       _gcount = 1;
  60.     }
  61.     }
  62.     return *this;
  63. }
  64.  
  65. int istream::peek()
  66. {
  67.   if (!good())
  68.     return EOF;
  69.   if (_tie && rdbuf()->in_avail() == 0)
  70.     _tie->flush();
  71.   int ch = _strbuf->sgetc();
  72.   if (ch == EOF)
  73.     set(ios::eofbit);
  74.   return ch;
  75. }
  76.  
  77. istream& istream::ignore(_G_size_t n1 /* = 1 */, int delim /* = EOF */)
  78. {
  79.     long n = n1;
  80.     if (ipfx1()) {
  81.     register streambuf* sb = _strbuf;
  82.     if (delim == EOF) {
  83.         _gcount = sb->ignore(n);
  84.         return *this;
  85.     }
  86.     _gcount = 0;
  87.     for (;;) {
  88. #if 0
  89.         if (n != MAXINT) // FIXME
  90. #endif
  91.         if (--n < 0)
  92.         break;
  93.         int ch = sb->sbumpc();
  94.         if (ch == EOF) {
  95.         set(ios::eofbit|ios::failbit);
  96.         break;
  97.         }
  98.         _gcount++;
  99.         if (ch == delim)
  100.         break;
  101.     }
  102.     }
  103.     return *this;
  104. }
  105.  
  106. istream& istream::read(char *s, _G_size_t n)
  107. {
  108.     if (ipfx1()) {
  109.     _gcount = _strbuf->sgetn(s, n);
  110.     if (_gcount != n)
  111.         set(ios::failbit);
  112.     }
  113.     return *this;
  114. }
  115.  
  116. istream& istream::seekg(streampos pos)
  117. {
  118.     pos = _strbuf->seekpos(pos, ios::in);
  119.     if (pos == streampos(EOF))
  120.     set(ios::badbit);
  121.     return *this;
  122. }
  123.  
  124. istream& istream::seekg(streamoff off, _seek_dir dir)
  125. {
  126.     streampos pos = _strbuf->seekoff(off, dir, ios::in);
  127.     if (pos == streampos(EOF))
  128.     set(ios::badbit);
  129.     return *this;
  130. }
  131.  
  132. streampos istream::tellg()
  133. {
  134.     streampos pos = _strbuf->seekoff(0, ios::cur, ios::in);
  135.     if (pos == streampos(EOF))
  136.     set(ios::badbit);
  137.     return pos;
  138. }
  139.  
  140. istream& istream::scan(const char *format ...)
  141. {
  142.     if (ipfx0()) {
  143.     va_list ap;
  144.     va_start(ap, format);
  145.     _strbuf->vscan(format, ap, this);
  146.     va_end(ap);
  147.     }
  148.     return *this;
  149. }
  150.  
  151. istream& istream::vscan(const char *format, _G_va_list args)
  152. {
  153.     if (ipfx0())
  154.     _strbuf->vscan(format, args, this);
  155.     return *this;
  156. }
  157.  
  158. istream& istream::operator>>(char& c)
  159. {
  160.     if (ipfx0()) {
  161.     int ch = _strbuf->sbumpc();
  162.     if (ch == EOF)
  163.         set(ios::eofbit|ios::failbit);
  164.     else
  165.         c = (char)ch;
  166.     }
  167.     return *this;
  168. }
  169.  
  170. istream& istream::operator>>(char* ptr)
  171. {
  172.   register char *p = ptr;
  173.   int w = width(0);
  174.   if (ipfx0()) {
  175.     register streambuf* sb = _strbuf;
  176.     for (;;)
  177.       {
  178.     int ch = sb->sbumpc();
  179.     if (ch == EOF)
  180.       {
  181.         set(p == ptr ? (ios::eofbit|ios::failbit) : (ios::eofbit));
  182.         break;
  183.       }
  184.     else if (isspace(ch))
  185.       {
  186.         sb->sputbackc(ch);
  187.         break;
  188.       }
  189.     else if (w == 1)
  190.       {
  191.         set(ios::failbit);
  192.         sb->sputbackc(ch);
  193.         break;
  194.       }
  195.     else *p++ = ch;
  196.     w--;
  197.       }
  198.   }
  199.   *p = '\0';
  200.   return *this;
  201. }
  202.  
  203. #if defined(__GNUC__) && (!defined(atarist))
  204. #define LONGEST long long
  205. #else
  206. #define LONGEST long
  207. #endif
  208.  
  209. static int read_int(istream& stream, unsigned LONGEST& val, int& neg)
  210. {
  211.     if (!stream.ipfx0())
  212.     return 0;
  213.     register streambuf* sb = stream.rdbuf();
  214.     int base = 10;
  215.     int ndigits = 0;
  216.     register int ch = skip_ws(sb);
  217.     if (ch == EOF)
  218.     goto eof_fail;
  219.     neg = 0;
  220.     if (ch == '+') {
  221.     ch = skip_ws(sb);
  222.     }
  223.     else if (ch == '-') {
  224.     neg = 1;
  225.     ch = skip_ws(sb);
  226.     }
  227.     if (ch == EOF) goto eof_fail;
  228.     if (!(stream.flags() & ios::basefield)) {
  229.     if (ch == '0') {
  230.         ch = sb->sbumpc();
  231.         if (ch == EOF) {
  232.         val = 0;
  233.         return 1;
  234.         }
  235.         if (ch == 'x' || ch == 'X') {
  236.         base = 16;
  237.         ch = sb->sbumpc();
  238.         if (ch == EOF) goto eof_fail;
  239.         }
  240.         else {
  241.         sb->sputbackc(ch);
  242.         base = 8;
  243.         ch = '0';
  244.         }
  245.     }
  246.     }
  247.     else if ((stream.flags() & ios::basefield) == ios::hex)
  248.     base = 16;
  249.     else if ((stream.flags() & ios::basefield) == ios::oct)
  250.     base = 8;
  251.     val = 0;
  252.     for (;;) {
  253.     if (ch == EOF)
  254.         break;
  255.     int digit;
  256.     if (ch >= '0' && ch <= '9')
  257.         digit = ch - '0';
  258.     else if (ch >= 'A' && ch <= 'F')
  259.         digit = ch - 'A' + 10;
  260.     else if (ch >= 'a' && ch <= 'f')
  261.         digit = ch - 'a' + 10;
  262.     else
  263.         digit = 999;
  264.     if (digit >= base) {
  265.         sb->sputbackc(ch);
  266.         if (ndigits == 0)
  267.         goto fail;
  268.         else
  269.         return 1;
  270.     }
  271.     ndigits++;
  272.     val = base * val + digit;
  273.     ch = sb->sbumpc();
  274.     }
  275.     return 1;
  276.   fail:
  277.     stream.set(ios::failbit);
  278.     return 0;
  279.   eof_fail:
  280.     stream.set(ios::failbit|ios::eofbit);
  281.     return 0;
  282. }
  283.  
  284. #define READ_INT(TYPE) \
  285. istream& istream::operator>>(TYPE& i)\
  286. {\
  287.     unsigned LONGEST val; int neg;\
  288.     if (read_int(*this, val, neg)) {\
  289.     if (neg) val = -val;\
  290.     i = (TYPE)val;\
  291.     }\
  292.     return *this;\
  293. }
  294.  
  295. READ_INT(short)
  296. READ_INT(unsigned short)
  297. READ_INT(int)
  298. READ_INT(unsigned int)
  299. READ_INT(long)
  300. READ_INT(unsigned long)
  301. #ifdef __GNUG__
  302. READ_INT(long long)
  303. READ_INT(unsigned long long)
  304. #endif
  305.  
  306. istream& istream::operator>>(double& x)
  307. {
  308.     if (ipfx0())
  309.     scan("%lg", &x);
  310.     return *this;
  311. }
  312.  
  313. istream& istream::operator>>(float& x)
  314. {
  315.     if (ipfx0())
  316.     scan("%g", &x);
  317.     return *this;
  318. }
  319.  
  320. istream& istream::operator>>(register streambuf* sbuf)
  321. {
  322.     if (ipfx0()) {
  323.     register streambuf* inbuf = rdbuf();
  324.     // FIXME: Should optimize!
  325.     for (;;) {
  326.         register int ch = inbuf->sbumpc();
  327.         if (ch == EOF) {
  328.         set(ios::eofbit);
  329.         break;
  330.         }
  331.         if (sbuf->sputc(ch) == EOF) {
  332.         set(ios::failbit);
  333.         break;
  334.         }
  335.     }
  336.     }
  337.     return *this;
  338. }
  339.  
  340. ostream& ostream::operator<<(char c)
  341. {
  342.     if (opfx()) {
  343. #if 1
  344.     // This is what the cfront implementation does.
  345.     _strbuf->sputc(c);
  346. #else
  347.     // This is what cfront documentation and current ANSI drafts say.
  348.     int w = width(0);
  349.     char fill_char = fill();
  350.     register int padding = w > 0 ? w - 1 : 0;
  351.     register streambuf *sb = _strbuf;
  352.     if (!(flags() & ios::left)) // Default adjustment.
  353.         while (--padding >= 0) sb->sputc(fill_char);
  354.     sb->sputc(c);
  355.     if (flags() & ios::left) // Left adjustment.
  356.         while (--padding >= 0) sb->sputc(fill_char);
  357. #endif
  358.     osfx();
  359.     }
  360.     return *this;
  361. }
  362.  
  363. /* Write VAL on STREAM.
  364.    If SIGN<0, val is the absolute value of a negative number.
  365.    If SIGN>0, val is a signed non-negative number.
  366.    If SIGN==0, val is unsigned. */
  367.  
  368. static void write_int(ostream& stream, unsigned LONGEST val, int sign)
  369. {
  370. #define WRITE_BUF_SIZE (10 + sizeof(unsigned LONGEST) * 3)
  371.     char buf[WRITE_BUF_SIZE];
  372.     register char *buf_ptr = buf+WRITE_BUF_SIZE; // End of buf.
  373.     char *show_base = "";
  374.     int show_base_len = 0;
  375.     int show_pos = 0; // If 1, print a '+'.
  376.  
  377.     // Now do the actual conversion, placing the result at the *end* of buf.
  378.     // Note that we use separate code for decimal, octal, and hex,
  379.     // so we can divide by optimizable constants.
  380.     if ((stream.flags() & ios::basefield) == ios::oct) { // Octal
  381.     do {
  382.         *--buf_ptr = (val & 7) + '0';
  383.         val = val >> 3;
  384.     } while (val != 0);
  385.     if ((stream.flags() & ios::showbase) && (val != 0))
  386.         *--buf_ptr = '0';
  387.     }
  388.     else if ((stream.flags() & ios::basefield) == ios::hex) { // Hex
  389.     char *xdigs = (stream.flags() & ios::uppercase) ? "0123456789ABCDEF0X"
  390.         : "0123456789abcdef0x";
  391.     do {
  392.         *--buf_ptr = xdigs[val & 15];
  393.         val = val >> 4;
  394.     } while (val != 0);
  395.     if ((stream.flags() & ios::showbase) && (val != 0)) {
  396.         show_base = xdigs + 16; // Either "0X" or "0x".
  397.         show_base_len = 2;
  398.     }
  399.     }
  400.     else { // Decimal
  401. #ifdef __GNUC__
  402.     // Optimization:  Only use long long when we need to.
  403.     while (val > UINT_MAX) {
  404.         *--buf_ptr = (val % 10) + '0';
  405.         val /= 10;
  406.     }
  407.     // Use more efficient (int) arithmetic for the rest.
  408.     register unsigned int ival = (unsigned int)val;
  409. #else
  410.     register unsigned LONGEST ival = val;
  411. #endif
  412.     do {
  413.         *--buf_ptr = (ival % 10) + '0';
  414.         ival /= 10;
  415.     } while (ival != 0);
  416.     if (sign > 0 && (stream.flags() & ios::showpos))
  417.         show_pos=1;
  418.     }
  419.  
  420.     _G_size_t buf_len = buf+WRITE_BUF_SIZE - buf_ptr;
  421.     int w = stream.width(0);
  422.  
  423.     // Calculate padding.
  424.     _G_size_t len = buf_len+show_pos;
  425.     if (sign < 0) len++;
  426.     len += show_base_len;
  427.     _G_size_t padding = len > w ? 0 : w - len;
  428.  
  429.     // Do actual output.
  430.     register streambuf* sbuf = stream.rdbuf();
  431.     ios::fmtflags pad_kind =
  432.     stream.flags() & (ios::left|ios::right|ios::internal);
  433.     char fill_char = stream.fill();
  434.     if (padding > 0
  435.     && pad_kind != (ios::fmtflags)ios::left
  436.     && pad_kind != (ios::fmtflags)ios::internal) // Default (right) adjust.
  437.     sbuf->padn(fill_char, padding);
  438.     if (sign < 0) sbuf->sputc('-');
  439.     else if (show_pos) sbuf->sputc('+');
  440.     if (show_base_len)
  441.     sbuf->sputn(show_base, show_base_len);
  442.     if (pad_kind == (ios::fmtflags)ios::internal && padding > 0)
  443.     sbuf->padn(fill_char, padding);
  444.     sbuf->sputn(buf_ptr, buf_len);
  445.     if (pad_kind == (ios::fmtflags)ios::left && padding > 0) // Left adjustment
  446.     sbuf->padn(fill_char, padding);
  447.     stream.osfx();
  448. }
  449.  
  450. ostream& ostream::operator<<(int n)
  451. {
  452.     if (opfx()) {
  453.     int sign = 1;
  454.     if (n < 0 && (flags() & (ios::oct|ios::hex)) == 0)
  455.         n = -n, sign = -1;
  456.     write_int(*this, n, sign);
  457.     }
  458.     return *this;
  459. }
  460.  
  461. ostream& ostream::operator<<(unsigned int n)
  462. {
  463.     if (opfx())
  464.     write_int(*this, n, 0);
  465.     return *this;
  466. }
  467.  
  468.  
  469. ostream& ostream::operator<<(long n)
  470. {
  471.     if (opfx()) {
  472.     int sign = 1;
  473.     if (n < 0 && (flags() & (ios::oct|ios::hex)) == 0)
  474.         n = -n, sign = -1;
  475.     write_int(*this, n, sign);
  476.     }
  477.     return *this;
  478. }
  479.  
  480. ostream& ostream::operator<<(unsigned long n)
  481. {
  482.     if (opfx())
  483.     write_int(*this, n, 0);
  484.     return *this;
  485. }
  486.  
  487. #ifdef __GNUG__
  488. ostream& ostream::operator<<(long long n)
  489. {
  490.     if (opfx()) {
  491.     int sign = 1;
  492.     if (n < 0 && (flags() & (ios::oct|ios::hex)) == 0)
  493.         n = -n, sign = -1;
  494.     write_int(*this, n, sign);
  495.     }
  496.     return *this;
  497. }
  498.  
  499.  
  500. ostream& ostream::operator<<(unsigned long long n)
  501. {
  502.     if (opfx())
  503.     write_int(*this, n, 0);
  504.     return *this;
  505. }
  506. #endif /*__GNUG__*/
  507.  
  508. ostream& ostream::operator<<(double n)
  509. {
  510.     if (opfx()) {
  511.     // Uses __cvt_double (renamed from static cvt), in Chris Torek's
  512.     // stdio implementation.  The setup code uses the same logic
  513.     // as in __vsbprintf.C (also based on Torek's code).
  514.     int format_char;
  515. #if 0
  516.     if (flags() ios::showpos) sign = '+';
  517. #endif
  518.     if ((flags() & ios::floatfield) == ios::fixed)
  519.         format_char = 'f';
  520.     else if ((flags() & ios::floatfield) == ios::scientific)
  521.         format_char = flags() & ios::uppercase ? 'E' : 'e';
  522.     else
  523.         format_char = flags() & ios::uppercase ? 'G' : 'g';
  524.  
  525.     int fpprec = 0; // 'Extra' (suppressed) floating precision.
  526.     int prec = precision();
  527.     if (prec > MAXFRACT) {
  528.         if (flags() & (ios::fixed|ios::scientific) & ios::showpos)
  529.         fpprec = prec - MAXFRACT;
  530.         prec = MAXFRACT;
  531.     }
  532.     else if (prec <= 0 && !(flags() & ios::fixed))
  533.       prec = 6; /* default */
  534.  
  535.     // Do actual conversion.
  536. #ifdef USE_DTOA
  537.     if (__outfloat(n, rdbuf(), format_char, width(0),
  538.                prec, flags(), 0, fill()) < 0)
  539.         set(ios::badbit|ios::failbit); // ??
  540. #else
  541.     int negative;
  542.     char buf[BUF];
  543.     int sign = '\0';
  544.     char *cp = buf;
  545.     *cp = 0;
  546.     int size = __cvt_double(n, prec,
  547.                 flags() & ios::showpoint ? 0x80 : 0,
  548.                 &negative,
  549.                 format_char, cp, buf + sizeof(buf));
  550.     if (negative) sign = '-';
  551.     if (*cp == 0)
  552.         cp++;
  553.  
  554.     // Calculate padding.
  555.     int fieldsize = size + fpprec;
  556.     if (sign) fieldsize++;
  557.     int padding = 0;
  558.     int w = width(0);
  559.     if (fieldsize < w)
  560.         padding = w - fieldsize;
  561.  
  562.     // Do actual output.
  563.     register streambuf* sbuf = rdbuf();
  564.     register i;
  565.     char fill_char = fill();
  566.     ios::fmtflags pad_kind =
  567.         flags() & (ios::left|ios::right|ios::internal);
  568.     if (pad_kind != (ios::fmtflags)ios::left // Default (right) adjust.
  569.         && pad_kind != (ios::fmtflags)ios::internal)
  570.         for (i = padding; --i >= 0; ) sbuf->sputc(fill_char);
  571.     if (sign)
  572.         sbuf->sputc(sign);
  573.     if (pad_kind == (ios::fmtflags)ios::internal)
  574.         for (i = padding; --i >= 0; ) sbuf->sputc(fill_char);
  575.     
  576.     // Emit the actual concented field, followed by extra zeros.
  577.     sbuf->sputn(cp, size);
  578.     for (i = fpprec; --i >= 0; ) sbuf->sputc('0');
  579.  
  580.     if (pad_kind == (ios::fmtflags)ios::left) // Left adjustment
  581.         for (i = padding; --i >= 0; ) sbuf->sputc(fill_char);
  582. #endif
  583.     osfx();
  584.     }
  585.     return *this;
  586. }
  587.  
  588. ostream& ostream::operator<<(const char *s)
  589. {
  590.     if (opfx()) {
  591.     if (s == NULL)
  592.         s = "(null)";
  593.     _G_size_t len = strlen(s);
  594.     int w = width(0);
  595.     char fill_char = fill();
  596.     register streambuf *sbuf = rdbuf();
  597.     register int padding = w > len ? w - len : 0;
  598.     if (!(flags() & ios::left)) // Default adjustment.
  599.         while (--padding >= 0) sbuf->sputc(fill_char);
  600.     sbuf->sputn(s, len);
  601.     if (flags() & ios::left) // Left adjustment.
  602.         while (--padding >= 0) sbuf->sputc(fill_char);
  603.     osfx();
  604.     }
  605.     return *this;
  606. }
  607.  
  608. ostream& ostream::operator<<(const void *p)
  609. {
  610.     if (opfx()) {
  611.     form("%p", p);
  612.     osfx();
  613.     }
  614.     return *this;
  615. }
  616.  
  617. ostream& ostream::operator<<(register streambuf* sbuf)
  618. {
  619.     if (opfx()) {
  620.     register streambuf* outbuf = rdbuf();
  621.     // FIXME: Should optimize!
  622.     for (;;) {
  623.         register int ch = sbuf->sbumpc();
  624.         if (ch == EOF) break;
  625.         if (outbuf->sputc(ch) == EOF) {
  626.         set(ios::badbit);
  627.         break;
  628.         }
  629.     }
  630.     osfx();
  631.     }
  632.     return *this;
  633. }
  634.  
  635. ostream::ostream(streambuf* sb, ostream* tied) : ios(sb, tied)
  636. {
  637.     _flags |= ios::dont_close;
  638. }
  639.  
  640. ostream& ostream::seekp(streampos pos)
  641. {
  642.     pos = _strbuf->seekpos(pos, ios::out);
  643.     if (pos == streampos(EOF))
  644.     set(ios::badbit);
  645.     return *this;
  646. }
  647.  
  648. ostream& ostream::seekp(streamoff off, _seek_dir dir)
  649. {
  650.     streampos pos = _strbuf->seekoff(off, dir, ios::out);
  651.     if (pos == streampos(EOF))
  652.     set(ios::badbit);
  653.     return *this;
  654. }
  655.  
  656. streampos ostream::tellp()
  657. {
  658.     streampos pos = _strbuf->seekoff(0, ios::cur, ios::out);
  659.     if (pos == streampos(EOF))
  660.     set(ios::badbit);
  661.     return pos;
  662. }
  663.  
  664. ostream& ostream::form(const char *format ...)
  665. {
  666.     if (opfx()) {
  667.     va_list ap;
  668.     va_start(ap, format);
  669.     _strbuf->vform(format, ap);
  670.     va_end(ap);
  671.     }
  672.     return *this;
  673. }
  674.  
  675. ostream& ostream::vform(const char *format, _G_va_list args)
  676. {
  677.     if (opfx())
  678.     _strbuf->vform(format, args);
  679.     return *this;
  680. }
  681.  
  682. ostream& ostream::flush()
  683. {
  684.     if (_strbuf->sync())
  685.     set(ios::badbit);
  686.     return *this;
  687. }
  688.  
  689. ostream& flush(ostream& outs)
  690. {
  691.   return outs.flush();
  692. }
  693.  
  694. istream& ws(istream& ins)
  695. {
  696.     if (ins.ipfx1()) {
  697.     int ch = skip_ws(ins._strbuf);
  698.     if (ch == EOF)
  699.         ins.set(ios::eofbit);
  700.     else
  701.         ins._strbuf->sputbackc(ch);
  702.     }
  703.     return ins;
  704. }
  705.  
  706. // Skip white-space.  Return 0 on failure (EOF), or 1 on success.
  707. // Differs from ws() manipulator in that failbit is set on EOF.
  708. // Called by ipfx() and ipfx0() if needed.
  709.  
  710. int istream::_skip_ws()
  711. {
  712.     int ch = skip_ws(_strbuf);
  713.     if (ch == EOF) {
  714.     set(ios::eofbit|ios::failbit);
  715.     return 0;
  716.     }
  717.     else {
  718.     _strbuf->sputbackc(ch);
  719.     return 1;
  720.     }
  721. }
  722.  
  723. ostream& ends(ostream& outs)
  724. {
  725.     outs.put('\0');
  726.     return outs;
  727. }
  728.  
  729. ostream& endl(ostream& outs)
  730. {
  731.     return flush(outs.put('\n'));
  732. }
  733.  
  734. ostream& ostream::write(const char *s, _G_size_t n)
  735. {
  736.     if (opfx()) {
  737.     if (_strbuf->sputn(s, n) != n)
  738.         set(ios::failbit);
  739.     }
  740.     return *this;
  741. }
  742.  
  743. void ostream::do_osfx()
  744. {
  745.     if (flags() & ios::unitbuf)
  746.     flush();
  747.     if (flags() & ios::stdio) {
  748.     fflush(stdout);
  749.     fflush(stderr);
  750.     }
  751. }
  752.  
  753. iostream::iostream(streambuf* sb, ostream* tied) : ios(sb, tied)
  754. {
  755.     _flags |= ios::dont_close;
  756.     _gcount = 0;
  757. }
  758.  
  759. // NOTE: extension for compatibility with old libg++.
  760. // Not really compatible with fistream::close().
  761. #ifdef _STREAM_COMPAT
  762. void ios::close()
  763. {
  764.     if (!(_flags & (unsigned int)ios::dont_close))
  765.     delete _strbuf;
  766.     else if (_strbuf->_flags & _S_IS_FILEBUF)
  767.     ((struct filebuf*)_strbuf)->close();
  768.     else if (_strbuf != NULL)
  769.     _strbuf->sync();
  770.     _flags |= ios::dont_close;
  771.     _strbuf = NULL;
  772.     _state = badbit;
  773. }
  774.  
  775. int istream::skip(_G_size_t i)
  776. {
  777.     int old = (_flags & ios::skipws) != 0;
  778.     if (i)
  779.     _flags |= ios::skipws;
  780.     else
  781.     _flags &= ~ios::skipws;
  782.     return old;
  783. }
  784. #endif
  785.