OSDN Git Service

Handle __set_errno correctly.
[pf3gnuchains/gcc-fork.git] / libio / iostream.cc
1 /* This is part of libio/iostream, providing -*- C++ -*- input/output.
2    Copyright (C) 1993, 1997 Free Software Foundation, Inc.
3
4    This file is part of the GNU IO Library.  This library is free
5    software; you can redistribute it and/or modify it under the
6    terms of the GNU General Public License as published by the
7    Free Software Foundation; either version 2, or (at your option)
8    any later version.
9
10    This library is distributed in the hope that it will be useful,
11    but WITHOUT ANY WARRANTY; without even the implied warranty of
12    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
13    GNU General Public License for more details.
14
15    You should have received a copy of the GNU General Public License
16    along with this library; see the file COPYING.  If not, write to the Free
17    Software Foundation, 59 Temple Place - Suite 330, Boston, MA  02111-1307,
18    USA.
19
20    As a special exception, if you link this library with files
21    compiled with a GNU compiler to produce an executable, this does not cause
22    the resulting executable to be covered by the GNU General Public License.
23    This exception does not however invalidate any other reasons why
24    the executable file might be covered by the GNU General Public License. */
25
26 /* Written by Per Bothner (bothner@cygnus.com). */
27
28 #ifdef __GNUC__
29 #pragma implementation
30 #endif
31 #define _STREAM_COMPAT
32 #include <iostream.h>
33 #include "libioP.h"
34 #include <stdio.h>  /* Needed for sprintf */
35 #include <ctype.h>
36 #include <string.h>
37 #include <limits.h>
38
39 #if _G_HAVE_PRINTF_FP
40 #include <printf.h>
41 extern "C" int __printf_fp (_IO_FILE *, const struct printf_info *,
42                             const void *const *);
43 #else
44 #include "floatio.h"
45 #endif
46
47 #define BUF             (MAXEXP+MAXFRACT+1)     /* + decimal point */
48
49 //#define isspace(ch) ((ch)==' ' || (ch)=='\t' || (ch)=='\n')
50
51 istream::istream(streambuf *sb, ostream* tied)
52 {
53   init (sb, tied);
54   _gcount = 0;
55 }
56
57 int skip_ws(streambuf* sb)
58 {
59     int ch;
60     for (;;) {
61         ch = sb->sbumpc();
62         if (ch == EOF || !isspace(ch))
63             return ch;
64     }
65 }
66
67 istream& istream::get(char& c)
68 {
69     if (ipfx1()) {
70         int ch = _strbuf->sbumpc();
71         if (ch == EOF) {
72           set(ios::eofbit|ios::failbit);
73           _gcount = 0;
74         }
75         else {
76           c = (char)ch;
77           _gcount = 1;
78         }
79     }
80     else
81       _gcount = 0;
82     return *this;
83 }
84
85 int istream::peek()
86 {
87   if (!good())
88     return EOF;
89   if (_tie && rdbuf()->in_avail() == 0)
90     _tie->flush();
91   int ch = _strbuf->sgetc();
92   if (ch == EOF)
93     set(ios::eofbit);
94   return ch;
95 }
96
97 istream& istream::ignore(int n /* = 1 */, int delim /* = EOF */)
98 {
99     _gcount = 0;
100     if (ipfx1()) {
101         register streambuf* sb = _strbuf;
102         if (delim == EOF) {
103             _gcount = sb->ignore(n);
104             return *this;
105         }
106         for (;;) {
107 #if 0
108             if (n != MAXINT) // FIXME
109 #endif
110             if (--n < 0)
111                 break;
112             int ch = sb->sbumpc();
113             if (ch == EOF) {
114                 set(ios::eofbit|ios::failbit);
115                 break;
116             }
117             _gcount++;
118             if (ch == delim)
119                 break;
120         }
121     }
122     return *this;
123 }
124
125 istream& istream::read(char *s, streamsize n)
126 {
127     if (ipfx1()) {
128         _gcount = _strbuf->sgetn(s, n);
129         if (_gcount != n)
130             set(ios::failbit|ios::eofbit);
131     }
132     else
133       _gcount = 0;
134     return *this;
135 }
136
137 int
138 istream::sync ()
139 {
140   streambuf *sb = rdbuf ();
141   if (sb == NULL)
142     return EOF;
143   if (sb->sync ()) // Later: pubsync
144     {
145       setstate (ios::badbit);
146       return EOF;
147     }
148   else
149     return 0;
150 }
151
152 istream& istream::seekg(streampos pos)
153 {
154     pos = _strbuf->pubseekpos(pos, ios::in);
155     if (pos == streampos(EOF))
156         set(ios::badbit);
157     return *this;
158 }
159
160 istream& istream::seekg(streamoff off, _seek_dir dir)
161 {
162   streampos pos = _IO_seekoff (_strbuf, off, (int) dir, _IOS_INPUT);
163   if (pos == streampos(EOF))
164     set(ios::badbit);
165   return *this;
166 }
167
168 streampos istream::tellg()
169 {
170 #if 0
171     streampos pos = _strbuf->pubseekoff(0, ios::cur, ios::in);
172 #else
173     streampos pos = _IO_seekoff (_strbuf, 0, _IO_seek_cur, _IOS_INPUT);
174 #endif
175     if (pos == streampos(EOF))
176         set(ios::badbit);
177     return pos;
178 }
179
180 istream& istream::operator>>(char& c)
181 {
182     if (ipfx0()) {
183         int ch = _strbuf->sbumpc();
184         if (ch == EOF)
185             set(ios::eofbit|ios::failbit);
186         else
187             c = (char)ch;
188     }
189     return *this;
190 }
191
192 istream&
193 istream::operator>> (char* ptr)
194 {
195   register char *p = ptr;
196   int w = width(0);
197   if (ipfx0())
198     {
199       register streambuf* sb = _strbuf;
200       for (;;)
201         {
202           int ch = sb->sbumpc();
203           if (ch == EOF)
204             {
205               set(ios::eofbit);
206               break;
207             }
208           else if (isspace(ch) || w == 1)
209             {
210               sb->sputbackc(ch);
211               break;
212             }
213           else *p++ = ch;
214           w--;
215         }
216       if (p == ptr)
217         set(ios::failbit);
218     }
219   *p = '\0';
220   return *this;
221 }
222
223 #if defined(__GNUC__) && !defined(__STRICT_ANSI__)
224 #define LONGEST long long
225 #else
226 #define LONGEST long
227 #endif
228
229 static int read_int(istream& stream, unsigned LONGEST& val, int& neg)
230 {
231     if (!stream.ipfx0())
232       return 0;
233     register streambuf* sb = stream.rdbuf();
234     int base = 10;
235     int ndigits = 0;
236     register int ch = skip_ws(sb);
237     if (ch == EOF)
238         goto eof_fail;
239     neg = 0;
240     if (ch == '+') {
241         ch = skip_ws(sb);
242     }
243     else if (ch == '-') {
244         neg = 1;
245         ch = skip_ws(sb);
246     }
247     if (ch == EOF) goto eof_fail;
248     if (!(stream.flags() & ios::basefield)) {
249         if (ch == '0') {
250             ch = sb->sbumpc();
251             if (ch == EOF) {
252                 val = 0;
253                 return 1;
254             }
255             if (ch == 'x' || ch == 'X') {
256                 base = 16;
257                 ch = sb->sbumpc();
258                 if (ch == EOF) goto eof_fail;
259             }
260             else {
261                 sb->sputbackc(ch);
262                 base = 8;
263                 ch = '0';
264             }
265         }
266     }
267     else if ((stream.flags() & ios::basefield) == ios::hex)
268         base = 16;
269     else if ((stream.flags() & ios::basefield) == ios::oct)
270         base = 8;
271     val = 0;
272     for (;;) {
273         if (ch == EOF)
274             break;
275         int digit;
276         if (ch >= '0' && ch <= '9')
277             digit = ch - '0';
278         else if (ch >= 'A' && ch <= 'F')
279             digit = ch - 'A' + 10;
280         else if (ch >= 'a' && ch <= 'f')
281             digit = ch - 'a' + 10;
282         else
283             digit = 999;
284         if (digit >= base) {
285             sb->sputbackc(ch);
286             if (ndigits == 0)
287                 goto fail;
288             else
289                 return 1;
290         }
291         ndigits++;
292         val = base * val + digit;
293         ch = sb->sbumpc();
294     }
295     return 1;
296   fail:
297     stream.set(ios::failbit);
298     return 0;
299   eof_fail:
300     stream.set(ios::failbit|ios::eofbit);
301     return 0;
302 }
303
304 #define READ_INT(TYPE) \
305 istream& istream::operator>>(TYPE& i)\
306 {\
307     unsigned LONGEST val; int neg;\
308     if (read_int(*this, val, neg)) {\
309         if (neg) val = -val;\
310         i = (TYPE)val;\
311     }\
312     return *this;\
313 }
314
315 READ_INT(short)
316 READ_INT(unsigned short)
317 READ_INT(int)
318 READ_INT(unsigned int)
319 READ_INT(long)
320 READ_INT(unsigned long)
321 #if defined(__GNUC__) && !defined(__STRICT_ANSI__)
322 READ_INT(long long)
323 READ_INT(unsigned long long)
324 #endif
325 #if _G_HAVE_BOOL
326 READ_INT(bool)
327 #endif
328
329 istream& istream::operator>>(long double& x)
330 {
331     if (ipfx0())
332 #if _G_HAVE_LONG_DOUBLE_IO
333         scan("%Lg", &x);
334 #else
335         scan("%lg", &x);
336 #endif
337     return *this;
338 }
339
340 istream& istream::operator>>(double& x)
341 {
342     if (ipfx0())
343         scan("%lg", &x);
344     return *this;
345 }
346
347 istream& istream::operator>>(float& x)
348 {
349     if (ipfx0())
350         scan("%g", &x);
351     return *this;
352 }
353
354 istream& istream::operator>>(register streambuf* sbuf)
355 {
356     if (ipfx0()) {
357         register streambuf* inbuf = rdbuf();
358         // FIXME: Should optimize!
359         for (;;) {
360             register int ch = inbuf->sbumpc();
361             if (ch == EOF) {
362                 set(ios::eofbit);
363                 break;
364             }
365             if (sbuf->sputc(ch) == EOF) {
366                 set(ios::failbit);
367                 break;
368             }
369         }
370     }
371     return *this;
372 }
373
374 ostream& ostream::operator<<(char c)
375 {
376     if (opfx()) {
377         _IO_cleanup_region_start ((void (*) __P ((void *))) _IO_funlockfile,
378                                   _strbuf);
379 #if 1
380         // This is what the cfront implementation does.
381         if (_strbuf->sputc(c) == EOF) {
382             set(ios::badbit);
383             goto failed;
384         }
385 #else
386         // This is what cfront documentation and current ANSI drafts say.
387         int w = width(0);
388         char fill_char = fill();
389         register int padding = w > 0 ? w - 1 : 0;
390         register streambuf *sb = _strbuf;
391         if (!(flags() & ios::left) && padding) // Default adjustment.
392             if (_IO_padn(sb, fill_char, padding) < padding) {
393               set(ios::badbit);
394               goto failed;
395             }
396         if (sb->sputc(c) == EOF) {
397           set(ios::badbit);
398           goto failed;
399         }
400         if (flags() & ios::left && padding) // Left adjustment.
401             if (_IO_padn(sb, fill_char, padding) < padding)
402               set(ios::badbit);
403 #endif
404        failed:
405         osfx();
406         _IO_cleanup_region_end (0);
407     }
408     return *this;
409 }
410
411 /* Write VAL on STREAM.
412    If SIGN<0, val is the absolute value of a negative number.
413    If SIGN>0, val is a signed non-negative number.
414    If SIGN==0, val is unsigned. */
415
416 static void write_int(ostream& stream, unsigned LONGEST val, int sign)
417 {
418 #define WRITE_BUF_SIZE (10 + sizeof(unsigned LONGEST) * 3)
419     char buf[WRITE_BUF_SIZE];
420     register char *buf_ptr = buf+WRITE_BUF_SIZE; // End of buf.
421     const char *show_base = "";
422     int show_base_len = 0;
423     int show_pos = 0; // If 1, print a '+'.
424
425     // Now do the actual conversion, placing the result at the *end* of buf.
426     // Note that we use separate code for decimal, octal, and hex,
427     // so we can divide by optimizable constants.
428     if ((stream.flags() & ios::basefield) == ios::oct) { // Octal
429         do {
430             *--buf_ptr = (val & 7) + '0';
431             val = val >> 3;
432         } while (val != 0);
433         if ((stream.flags() & ios::showbase) && (*buf_ptr != '0'))
434             *--buf_ptr = '0';
435     }
436     else if ((stream.flags() & ios::basefield) == ios::hex) { // Hex
437         const char *xdigs = (stream.flags() & ios::uppercase) ? "0123456789ABCDEF0X"
438             : "0123456789abcdef0x";
439         do {
440             *--buf_ptr = xdigs[val & 15];
441             val = val >> 4;
442         } while (val != 0);
443         if ((stream.flags() & ios::showbase)) {
444             show_base = xdigs + 16; // Either "0X" or "0x".
445             show_base_len = 2;
446         }
447     }
448     else { // Decimal
449 #if defined(__GNUC__) && !defined(__STRICT_ANSI__)
450         // Optimization:  Only use long long when we need to.
451         while (val > UINT_MAX) {
452             *--buf_ptr = (val % 10) + '0';
453             val /= 10;
454         }
455         // Use more efficient (int) arithmetic for the rest.
456         register unsigned int ival = (unsigned int)val;
457 #else
458         register unsigned LONGEST ival = val;
459 #endif
460         do {
461             *--buf_ptr = (ival % 10) + '0';
462             ival /= 10;
463         } while (ival != 0);
464         if (sign > 0 && (stream.flags() & ios::showpos))
465             show_pos=1;
466     }
467
468     int buf_len = buf+WRITE_BUF_SIZE - buf_ptr;
469     int w = stream.width(0);
470
471     // Calculate padding.
472     int len = buf_len+show_pos;
473     if (sign < 0) len++;
474     len += show_base_len;
475     int padding = len > w ? 0 : w - len;
476
477     // Do actual output.
478     register streambuf* sbuf = stream.rdbuf();
479     ios::fmtflags pad_kind =
480         stream.flags() & (ios::left|ios::right|ios::internal);
481     char fill_char = stream.fill();
482     if (padding > 0
483         && pad_kind != (ios::fmtflags)ios::left
484         && pad_kind != (ios::fmtflags)ios::internal) // Default (right) adjust.
485         if (_IO_padn(sbuf, fill_char, padding) < padding)
486           goto failed;
487     if (sign < 0 || show_pos)
488       {
489         char ch = sign < 0 ? '-' : '+';
490         if (sbuf->sputc(ch) < 0)
491           goto failed;
492       }
493     if (show_base_len)
494         if (_IO_sputn(sbuf, show_base, show_base_len) <= 0)
495           goto failed;
496     if (pad_kind == (ios::fmtflags)ios::internal && padding > 0)
497       if (_IO_padn(sbuf, fill_char, padding) < padding)
498         goto failed;
499     if (_IO_sputn (sbuf, buf_ptr, buf_len) != buf_len)
500       goto failed;
501     if (pad_kind == (ios::fmtflags)ios::left && padding > 0) // Left adjustment
502       if (_IO_padn(sbuf, fill_char, padding) < padding)
503         goto failed;
504     stream.osfx();
505     return;
506   failed:
507     stream.set(ios::badbit);
508     stream.osfx();
509 }
510
511 ostream& ostream::operator<<(int n)
512 {
513     if (opfx()) {
514         _IO_cleanup_region_start ((void (*) __P ((void *))) _IO_funlockfile,
515                                   _strbuf);
516         int sign = 1;
517         unsigned int abs_n = (unsigned)n;
518         if (n < 0 && (flags() & (ios::oct|ios::hex)) == 0)
519             abs_n = -((unsigned)n), sign = -1;
520         write_int(*this, abs_n, sign);
521         _IO_cleanup_region_end (0);
522     }
523     return *this;
524 }
525
526 ostream& ostream::operator<<(unsigned int n)
527 {
528     if (opfx()) {
529         _IO_cleanup_region_start ((void (*) __P ((void *))) _IO_funlockfile,
530                                   _strbuf);
531         write_int(*this, n, 0);
532         _IO_cleanup_region_end (0);
533     }
534     return *this;
535 }
536
537
538 ostream& ostream::operator<<(long n)
539 {
540     if (opfx()) {
541         _IO_cleanup_region_start ((void (*) __P ((void *))) _IO_funlockfile,
542                                   _strbuf);
543         int sign = 1;
544         unsigned long abs_n = (unsigned long)n;
545         if (n < 0 && (flags() & (ios::oct|ios::hex)) == 0)
546             abs_n = -((unsigned long)n), sign = -1;
547         write_int(*this, abs_n, sign);
548         _IO_cleanup_region_end (0);
549     }
550     return *this;
551 }
552
553 ostream& ostream::operator<<(unsigned long n)
554 {
555     if (opfx()) {
556         _IO_cleanup_region_start ((void (*) __P ((void *))) _IO_funlockfile,
557                                   _strbuf);
558         write_int(*this, n, 0);
559         _IO_cleanup_region_end (0);
560     }
561     return *this;
562 }
563
564 #if defined(__GNUC__) && !defined(__STRICT_ANSI__)
565 ostream& ostream::operator<<(long long n)
566 {
567     if (opfx()) {
568         _IO_cleanup_region_start ((void (*) __P ((void *))) _IO_funlockfile,
569                                   _strbuf);
570         int sign = 1;
571         unsigned long long abs_n = (unsigned long long)n;
572         if (n < 0 && (flags() & (ios::oct|ios::hex)) == 0)
573             abs_n = -((unsigned long long)n), sign = -1;
574         write_int(*this, abs_n, sign);
575         _IO_cleanup_region_end (0);
576     }
577     return *this;
578 }
579
580
581 ostream& ostream::operator<<(unsigned long long n)
582 {
583     if (opfx()) {
584         _IO_cleanup_region_start ((void (*) __P ((void *))) _IO_funlockfile,
585                                   _strbuf);
586         write_int(*this, n, 0);
587         _IO_cleanup_region_end (0);
588     }
589     return *this;
590 }
591 #endif /*__GNUC__*/
592
593 ostream& ostream::operator<<(double n)
594 {
595     if (opfx()) {
596         _IO_cleanup_region_start ((void (*) __P ((void *))) _IO_funlockfile,
597                                   _strbuf);
598         // Uses __cvt_double (renamed from static cvt), in Chris Torek's
599         // stdio implementation.  The setup code uses the same logic
600         // as in __vsbprintf.C (also based on Torek's code).
601         int format_char;
602         if ((flags() & ios::floatfield) == ios::fixed)
603             format_char = 'f';
604         else if ((flags() & ios::floatfield) == ios::scientific)
605             format_char = flags() & ios::uppercase ? 'E' : 'e';
606         else
607             format_char = flags() & ios::uppercase ? 'G' : 'g';
608
609         int prec = precision();
610         if (prec <= 0 && !(flags() & ios::fixed))
611           prec = 6; /* default */
612
613         // Do actual conversion.
614 #ifdef _G_HAVE_PRINTF_FP
615         {
616           struct printf_info info = { prec: prec,
617                                       width: width(0),
618                                       spec: format_char,
619                                       is_long_double: 0,
620                                       is_short: 0,
621                                       is_long: 0,
622                                       alt: flags() & ios::showpoint,
623                                       space: 0,
624                                       left: ios::left,
625                                       showsign: flags() & ios::showpos,
626                                       group: 0,
627                                       pad: fill(),
628                                       extra: 0};
629           const void *ptr = &n;
630           if (__printf_fp (rdbuf(), &info, &ptr) < 0)
631             set(ios::badbit|ios::failbit);
632         }
633 #elif defined  _IO_USE_DTOA
634         if (_IO_outfloat(n, rdbuf(), format_char, width(0),
635                          prec, flags(),
636                          flags() & ios::showpos ? '+' : 0,
637                          fill()) < 0)
638             set(ios::badbit|ios::failbit); // ??
639 #else
640         int fpprec = 0; // 'Extra' (suppressed) floating precision.
641         if (prec > MAXFRACT) {
642             if (flags() & (ios::fixed|ios::scientific) & ios::showpos)
643                 fpprec = prec - MAXFRACT;
644             prec = MAXFRACT;
645         }
646         int negative;
647         char buf[BUF];
648         int sign = '\0';
649         char *cp = buf;
650         *cp = 0;
651         int size = __cvt_double(n, prec,
652                                 flags() & ios::showpoint ? 0x80 : 0,
653                                 &negative,
654                                 format_char, cp, buf + sizeof(buf));
655         if (negative) sign = '-';
656         else if (flags() & ios::showpos) sign = '+';
657         if (*cp == 0)
658             cp++;
659
660         // Calculate padding.
661         int fieldsize = size + fpprec;
662         if (sign) fieldsize++;
663         int padding = 0;
664         int w = width(0);
665         if (fieldsize < w)
666             padding = w - fieldsize;
667
668         // Do actual output.
669         register streambuf* sbuf = rdbuf();
670         register i;
671         char fill_char = fill();
672         ios::fmtflags pad_kind =
673             flags() & (ios::left|ios::right|ios::internal);
674         if (pad_kind != (ios::fmtflags)ios::left // Default (right) adjust.
675             && pad_kind != (ios::fmtflags)ios::internal)
676             for (i = padding; --i >= 0; ) sbuf->sputc(fill_char);
677         if (sign)
678             sbuf->sputc(sign);
679         if (pad_kind == (ios::fmtflags)ios::internal)
680             for (i = padding; --i >= 0; ) sbuf->sputc(fill_char);
681
682         // Emit the actual concented field, followed by extra zeros.
683         _IO_sputn (sbuf, cp, size);
684         for (i = fpprec; --i >= 0; ) sbuf->sputc('0');
685
686         if (pad_kind == (ios::fmtflags)ios::left) // Left adjustment
687             for (i = padding; --i >= 0; ) sbuf->sputc(fill_char);
688 #endif
689         osfx();
690         _IO_cleanup_region_end (0);
691     }
692     return *this;
693 }
694
695 #if _G_HAVE_LONG_DOUBLE_IO
696 ostream& ostream::operator<<(long double n)
697 {
698   if (opfx())
699     {
700       _IO_cleanup_region_start ((void (*) __P ((void *))) _IO_funlockfile,
701                                 _strbuf);
702       int format_char;
703       if ((flags() & ios::floatfield) == ios::fixed)
704         format_char = 'f';
705       else if ((flags() & ios::floatfield) == ios::scientific)
706         format_char = flags() & ios::uppercase ? 'E' : 'e';
707       else
708         format_char = flags() & ios::uppercase ? 'G' : 'g';
709
710       int prec = precision();
711       if (prec <= 0 && !(flags() & ios::fixed))
712         prec = 6; /* default */
713
714 #ifdef _G_HAVE_PRINTF_FP
715       // Do actual conversion.
716       struct printf_info info = { prec: prec,
717                                   width: width(0),
718                                   spec: format_char,
719                                   is_long_double: 1,
720                                   is_short: 0,
721                                   is_long: 0,
722                                   alt: flags() & ios::showpoint,
723                                   space: 0,
724                                   left: ios::left,
725                                   showsign: flags() & ios::showpos,
726                                   group: 0,
727                                   pad: fill(),
728                                   extra: 0};
729
730       const void *ptr = &n;
731
732       if (__printf_fp (rdbuf(), &info, &ptr) < 0)
733         set (ios::badbit|ios::failbit);
734 #else
735 # error "long double I/O using dtoa or cvt_double is not implemented"
736 #endif
737       osfx();
738       _IO_cleanup_region_end (0);
739     }
740   return *this;
741 }
742 #endif
743
744 ostream& ostream::operator<<(const char *s)
745 {
746   if (opfx())
747     {
748       _IO_cleanup_region_start ((void (*) __P ((void *))) _IO_funlockfile,
749                                 _strbuf);
750       if (s == NULL)
751         s = "(null)";
752       int len = strlen(s);
753       int w = width(0);
754 // FIXME: Should we: if (w && len>w) len = w;
755       char fill_char = fill();
756       register streambuf *sbuf = rdbuf();
757       register int padding = w > len ? w - len : 0;
758       if (!(flags() & ios::left) && padding > 0) // Default adjustment.
759         if (_IO_padn(sbuf, fill_char, padding) != padding)
760           {
761             set(ios::badbit);
762             goto failed;
763           }
764       if (_IO_sputn (sbuf, s, len) != len)
765         {
766           set(ios::badbit);
767           goto failed;
768         }
769       if (flags() & ios::left && padding > 0) // Left adjustment.
770         if (_IO_padn(sbuf, fill_char, padding) != padding)
771           set(ios::badbit);
772       osfx();
773      failed:
774       _IO_cleanup_region_end (0);
775     }
776   return *this;
777 }
778
779 #if 0
780 ostream& ostream::operator<<(const void *p)
781 { Is in osform.cc, to avoid pulling in all of _IO_vfprintf by this file. */ }
782 #endif
783
784 ostream& ostream::operator<<(register streambuf* sbuf)
785 {
786   if (opfx())
787     {
788       _IO_cleanup_region_start ((void (*) __P ((void *))) _IO_funlockfile,
789                                 _strbuf);
790       char buffer[_IO_BUFSIZ];
791       register streambuf* outbuf = _strbuf;
792       for (;;)
793         {
794           _IO_size_t count = _IO_sgetn(sbuf, buffer, _IO_BUFSIZ);
795           if (count <= 0)
796             break;
797           if (_IO_sputn(outbuf, buffer, count) != count)
798             {
799               set(ios::badbit);
800               break;
801             }
802         }
803       osfx();
804       _IO_cleanup_region_end (0);
805     }
806   return *this;
807 }
808
809 ostream::ostream(streambuf* sb, ostream* tied)
810 {
811   init (sb, tied);
812 }
813
814 ostream& ostream::seekp(streampos pos)
815 {
816     pos = _strbuf->pubseekpos(pos, ios::out);
817     if (pos == streampos(EOF))
818         set(ios::badbit);
819     return *this;
820 }
821
822 ostream& ostream::seekp(streamoff off, _seek_dir dir)
823 {
824   streampos pos = _IO_seekoff (_strbuf, off, (int) dir, _IOS_OUTPUT);
825   if (pos == streampos(EOF))
826     set(ios::badbit);
827   return *this;
828 }
829
830 streampos ostream::tellp()
831 {
832 #if 1
833     streampos pos = _IO_seekoff (_strbuf, 0, _IO_seek_cur, _IOS_OUTPUT);
834 #else
835     streampos pos = _strbuf->pubseekoff(0, ios::cur, ios::out);
836 #endif
837     if (pos == streampos(EOF))
838         set(ios::badbit);
839     return pos;
840 }
841
842 ostream& ostream::flush()
843 {
844     if (_strbuf->sync())
845         set(ios::badbit);
846     return *this;
847 }
848
849 ostream& flush(ostream& outs)
850 {
851   return outs.flush();
852 }
853
854 istream& ws(istream& ins)
855 {
856     if (ins.ipfx1()) {
857         _IO_cleanup_region_start ((void (*) __P ((void *))) _IO_funlockfile,
858                                   ins._strbuf);
859         int ch = skip_ws(ins._strbuf);
860         if (ch == EOF)
861             ins.set(ios::eofbit);
862         else
863             ins._strbuf->sputbackc(ch);
864         ins.isfx();
865         _IO_cleanup_region_end (0);
866     }
867     return ins;
868 }
869
870 // Skip white-space.  Return 0 on failure (EOF), or 1 on success.
871 // Differs from ws() manipulator in that failbit is set on EOF.
872 // Called by ipfx() and ipfx0() if needed.
873
874 int istream::_skip_ws()
875 {
876     int ch = skip_ws(_strbuf);
877     if (ch == EOF) {
878         set(ios::eofbit|ios::failbit);
879         return 0;
880     }
881     else {
882         _strbuf->sputbackc(ch);
883         return 1;
884     }
885 }
886
887 ostream& ends(ostream& outs)
888 {
889     outs.put('\0');
890     return outs;
891 }
892
893 ostream& endl(ostream& outs)
894 {
895     return flush(outs.put('\n'));
896 }
897
898 istream& lock(istream& ins)
899 {
900   _IO_flockfile (ins._strbuf);
901   return ins;
902 }
903 istream& unlock(istream& ins)
904 {
905   _IO_funlockfile (ins._strbuf);
906   return ins;
907 }
908 ostream& lock(ostream& outs)
909 {
910   _IO_flockfile (outs._strbuf);
911   return outs;
912 }
913 ostream& unlock(ostream& outs)
914 {
915   _IO_funlockfile (outs._strbuf);
916   return outs;
917 }
918
919
920 ostream& ostream::write(const char *s, streamsize n)
921 {
922     if (opfx()) {
923         _IO_cleanup_region_start ((void (*) __P ((void *))) _IO_funlockfile,
924                                   _strbuf);
925         if (_IO_sputn(_strbuf, s, n) != n)
926             set(ios::failbit);
927         osfx();
928         _IO_cleanup_region_end (0);
929     }
930     return *this;
931 }
932
933 void ostream::do_osfx()
934 {
935     if (flags() & ios::unitbuf)
936         flush();
937     if (flags() & ios::stdio) {
938         fflush(stdout);
939         fflush(stderr);
940     }
941 }
942
943 iostream::iostream(streambuf* sb, ostream* tied)
944 {
945   init (sb, tied);
946 }
947
948 // NOTE: extension for compatibility with old libg++.
949 // Not really compatible with fistream::close().
950 #ifdef _STREAM_COMPAT
951 void ios::close()
952 {
953   if (_strbuf->_flags & _IO_IS_FILEBUF)
954     ((struct filebuf*)rdbuf())->close();
955   else if (_strbuf != NULL)
956     rdbuf()->sync();
957   _strbuf = NULL;
958   _state = badbit;
959 }
960
961 int istream::skip(int i)
962 {
963     int old = (_flags & ios::skipws) != 0;
964     if (i)
965         _flags |= ios::skipws;
966     else
967         _flags &= ~ios::skipws;
968     return old;
969 }
970 #endif