OSDN Git Service

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