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