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