OSDN Git Service

* flow.c (mark_used_regs): Improve handling of ASMs.
[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 #if __GLIBC_MINOR__ >= 1
638                                       /* is_char: */ 0,
639 #endif
640 #endif
641                                       /* pad: */ fill()
642           };
643           const void *ptr = (const void *) &n;
644           if (__printf_fp (rdbuf(), &info, &ptr) < 0)
645             set(ios::badbit|ios::failbit);
646         }
647 #elif defined  _IO_USE_DTOA
648         if (_IO_outfloat(n, rdbuf(), format_char, width(0),
649                          prec, flags(),
650                          flags() & ios::showpos ? '+' : 0,
651                          fill()) < 0)
652             set(ios::badbit|ios::failbit); // ??
653 #else
654         int fpprec = 0; // 'Extra' (suppressed) floating precision.
655         if (prec > MAXFRACT) {
656             if (flags() & (ios::fixed|ios::scientific) & ios::showpos)
657                 fpprec = prec - MAXFRACT;
658             prec = MAXFRACT;
659         }
660         int negative;
661         char buf[BUF];
662         int sign = '\0';
663         char *cp = buf;
664         *cp = 0;
665         int size = __cvt_double(n, prec,
666                                 flags() & ios::showpoint ? 0x80 : 0,
667                                 &negative,
668                                 format_char, cp, buf + sizeof(buf));
669         if (negative) sign = '-';
670         else if (flags() & ios::showpos) sign = '+';
671         if (*cp == 0)
672             cp++;
673
674         // Calculate padding.
675         int fieldsize = size + fpprec;
676         if (sign) fieldsize++;
677         int padding = 0;
678         int w = width(0);
679         if (fieldsize < w)
680             padding = w - fieldsize;
681
682         // Do actual output.
683         register streambuf* sbuf = rdbuf();
684         register i;
685         char fill_char = fill();
686         ios::fmtflags pad_kind =
687             flags() & (ios::left|ios::right|ios::internal);
688         if (pad_kind != (ios::fmtflags)ios::left // Default (right) adjust.
689             && pad_kind != (ios::fmtflags)ios::internal)
690             for (i = padding; --i >= 0; ) sbuf->sputc(fill_char);
691         if (sign)
692             sbuf->sputc(sign);
693         if (pad_kind == (ios::fmtflags)ios::internal)
694             for (i = padding; --i >= 0; ) sbuf->sputc(fill_char);
695
696         // Emit the actual concented field, followed by extra zeros.
697         _IO_sputn (sbuf, cp, size);
698         for (i = fpprec; --i >= 0; ) sbuf->sputc('0');
699
700         if (pad_kind == (ios::fmtflags)ios::left) // Left adjustment
701             for (i = padding; --i >= 0; ) sbuf->sputc(fill_char);
702 #endif
703         osfx();
704         _IO_cleanup_region_end (0);
705     }
706     return *this;
707 }
708
709 #if _G_HAVE_LONG_DOUBLE_IO
710 ostream& ostream::operator<<(long double n)
711 {
712   if (opfx())
713     {
714       _IO_cleanup_region_start ((void (*) __P ((void *))) _IO_funlockfile,
715                                 _strbuf);
716       int format_char;
717       if ((flags() & ios::floatfield) == ios::fixed)
718         format_char = 'f';
719       else if ((flags() & ios::floatfield) == ios::scientific)
720         format_char = flags() & ios::uppercase ? 'E' : 'e';
721       else
722         format_char = flags() & ios::uppercase ? 'G' : 'g';
723
724       int prec = precision();
725       if (prec <= 0 && !(flags() & ios::fixed))
726         prec = 6; /* default */
727
728 #if _G_HAVE_PRINTF_FP
729       // Do actual conversion.
730       struct printf_info info = { /* prec: */ prec,
731                                   /* width: */ width(0),
732                                   /* spec: */ format_char,
733                                   /* is_long_double: */ 1,
734                                   /* is_short: */ 0,
735                                   /* is_long: */ 0,
736                                   /* alt: */ (flags() & ios::showpoint) != 0,
737                                   /* space: */ 0,
738                                   /* left: */ (flags() & ios::left) != 0,
739                                   /* showsign: */ (flags() & ios::showpos) != 0,
740                                   /* group: */ 0,
741 #if defined __GLIBC__ && __GLIBC__ >= 2
742                                   /* extra: */ 0,
743 #if __GLIBC_MINOR__ >= 1
744                                   /* is_char: */ 0,
745 #endif
746 #endif
747                                   /* pad: */ fill()
748       };
749
750       const void *ptr = (const void *) &n;
751
752       if (__printf_fp (rdbuf(), &info, &ptr) < 0)
753         set (ios::badbit|ios::failbit);
754 #else
755 # error "long double I/O using dtoa or cvt_double is not implemented"
756 #endif
757       osfx();
758       _IO_cleanup_region_end (0);
759     }
760   return *this;
761 }
762 #endif
763
764 ostream& ostream::operator<<(const char *s)
765 {
766   if (opfx())
767     {
768       _IO_cleanup_region_start ((void (*) __P ((void *))) _IO_funlockfile,
769                                 _strbuf);
770       if (s == NULL)
771         s = "(null)";
772       int len = strlen(s);
773       int w = width(0);
774 // FIXME: Should we: if (w && len>w) len = w;
775       char fill_char = fill();
776       register streambuf *sbuf = rdbuf();
777       register int padding = w > len ? w - len : 0;
778       if (!(flags() & ios::left) && padding > 0) // Default adjustment.
779         if (_IO_padn(sbuf, fill_char, padding) != padding)
780           {
781             set(ios::badbit);
782             goto failed;
783           }
784       if (_IO_sputn (sbuf, s, len) != len)
785         {
786           set(ios::badbit);
787           goto failed;
788         }
789       if (flags() & ios::left && padding > 0) // Left adjustment.
790         if (_IO_padn(sbuf, fill_char, padding) != padding)
791           set(ios::badbit);
792       osfx();
793      failed:
794       _IO_cleanup_region_end (0);
795     }
796   return *this;
797 }
798
799 #if 0
800 ostream& ostream::operator<<(const void *p)
801 { Is in osform.cc, to avoid pulling in all of _IO_vfprintf by this file. */ }
802 #endif
803
804 ostream& ostream::operator<<(register streambuf* sbuf)
805 {
806   if (opfx())
807     {
808       _IO_cleanup_region_start ((void (*) __P ((void *))) _IO_funlockfile,
809                                 _strbuf);
810       char buffer[_IO_BUFSIZ];
811       register streambuf* outbuf = _strbuf;
812       for (;;)
813         {
814           _IO_size_t count = _IO_sgetn(sbuf, buffer, _IO_BUFSIZ);
815           if (count <= 0)
816             break;
817           if (_IO_sputn(outbuf, buffer, count) != count)
818             {
819               set(ios::badbit);
820               break;
821             }
822         }
823       osfx();
824       _IO_cleanup_region_end (0);
825     }
826   return *this;
827 }
828
829 ostream::ostream(streambuf* sb, ostream* tied)
830 {
831   init (sb, tied);
832 }
833
834 ostream& ostream::seekp(streampos pos)
835 {
836     pos = _strbuf->pubseekpos(pos, ios::out);
837     if (pos == streampos(EOF))
838         set(ios::badbit);
839     return *this;
840 }
841
842 ostream& ostream::seekp(streamoff off, _seek_dir dir)
843 {
844   streampos pos = _IO_seekoff (_strbuf, off, (int) dir, _IOS_OUTPUT);
845   if (pos == streampos(EOF))
846     set(ios::badbit);
847   return *this;
848 }
849
850 streampos ostream::tellp()
851 {
852 #if 1
853     streampos pos = _IO_seekoff (_strbuf, 0, _IO_seek_cur, _IOS_OUTPUT);
854 #else
855     streampos pos = _strbuf->pubseekoff(0, ios::cur, ios::out);
856 #endif
857     if (pos == streampos(EOF))
858         set(ios::badbit);
859     return pos;
860 }
861
862 ostream& ostream::flush()
863 {
864     if (_strbuf->sync())
865         set(ios::badbit);
866     return *this;
867 }
868
869 ostream& flush(ostream& outs)
870 {
871   return outs.flush();
872 }
873
874 istream& ws(istream& ins)
875 {
876     if (ins.ipfx1()) {
877         _IO_cleanup_region_start ((void (*) __P ((void *))) _IO_funlockfile,
878                                   ins._strbuf);
879         int ch = skip_ws(ins._strbuf);
880         if (ch == EOF)
881             ins.set(ios::eofbit);
882         else
883             ins._strbuf->sputbackc(ch);
884         ins.isfx();
885         _IO_cleanup_region_end (0);
886     }
887     return ins;
888 }
889
890 // Skip white-space.  Return 0 on failure (EOF), or 1 on success.
891 // Differs from ws() manipulator in that failbit is set on EOF.
892 // Called by ipfx() and ipfx0() if needed.
893
894 int istream::_skip_ws()
895 {
896     int ch = skip_ws(_strbuf);
897     if (ch == EOF) {
898         set(ios::eofbit|ios::failbit);
899         return 0;
900     }
901     else {
902         _strbuf->sputbackc(ch);
903         return 1;
904     }
905 }
906
907 ostream& ends(ostream& outs)
908 {
909     outs.put('\0');
910     return outs;
911 }
912
913 ostream& endl(ostream& outs)
914 {
915     return flush(outs.put('\n'));
916 }
917
918 istream& lock(istream& ins)
919 {
920   _IO_flockfile (ins._strbuf);
921   return ins;
922 }
923 istream& unlock(istream& ins)
924 {
925   _IO_funlockfile (ins._strbuf);
926   return ins;
927 }
928 ostream& lock(ostream& outs)
929 {
930   _IO_flockfile (outs._strbuf);
931   return outs;
932 }
933 ostream& unlock(ostream& outs)
934 {
935   _IO_funlockfile (outs._strbuf);
936   return outs;
937 }
938
939
940 ostream& ostream::write(const char *s, streamsize n)
941 {
942     if (opfx()) {
943         _IO_cleanup_region_start ((void (*) __P ((void *))) _IO_funlockfile,
944                                   _strbuf);
945         if (_IO_sputn(_strbuf, s, n) != n)
946             set(ios::failbit);
947         osfx();
948         _IO_cleanup_region_end (0);
949     }
950     return *this;
951 }
952
953 void ostream::do_osfx()
954 {
955     if (flags() & ios::unitbuf)
956         flush();
957     if (flags() & ios::stdio) {
958         fflush(stdout);
959         fflush(stderr);
960     }
961 }
962
963 iostream::iostream(streambuf* sb, ostream* tied)
964 {
965   init (sb, tied);
966 }
967
968 // NOTE: extension for compatibility with old libg++.
969 // Not really compatible with fistream::close().
970 #ifdef _STREAM_COMPAT
971 void ios::close()
972 {
973   if (_strbuf->_flags & _IO_IS_FILEBUF)
974     ((struct filebuf*)rdbuf())->close();
975   else if (_strbuf != NULL)
976     rdbuf()->sync();
977   _strbuf = NULL;
978   _state = badbit;
979 }
980
981 int istream::skip(int i)
982 {
983     int old = (_flags & ios::skipws) != 0;
984     if (i)
985         _flags |= ios::skipws;
986     else
987         _flags &= ~ios::skipws;
988     return old;
989 }
990 #endif