OSDN Git Service

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