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>
41extern "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
46int __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
55istream::istream(streambuf *sb, ostream* tied)
56{
57  init (sb, tied);
58  _gcount = 0;
59}
60
61int 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
71istream& 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
93int 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
106istream& istream::read(char *ptr, int n)
107{
108  return read((char*)ptr, (streamsize)n);
109}
110istream& istream::read(unsigned char *ptr, int n)
111{
112  return read((char*)ptr, (streamsize)n);
113}
114istream& istream::read(signed char *ptr, int n)
115{
116  return read((char*)ptr, (streamsize)n);
117}
118istream& istream::read(void *ptr, int n)
119{
120  return read((char*)ptr, (streamsize)n);
121}
122
123istream& 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
156istream& 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
172int
173istream::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
187istream& 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
195istream& 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
203streampos 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
215istream& 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
231istream&
232istream::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
272static 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) \
358istream& 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
368READ_INT(short)
369READ_INT(unsigned short)
370READ_INT(int)
371READ_INT(unsigned int)
372READ_INT(long)
373READ_INT(unsigned long)
374#if defined(__GNUC__) && !defined(__STRICT_ANSI__)
375READ_INT(long long)
376READ_INT(unsigned long long)
377#endif
378#if _G_HAVE_BOOL
379READ_INT(bool)
380#endif
381
382static 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
395istream& 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
414istream& 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
427istream& 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
440istream& 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
464ostream& 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
506static 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
601ostream& 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
616ostream& 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
628ostream& 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
643ostream& 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__)
655ostream& 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
671ostream& 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
683ostream& 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
796ostream& 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
854ostream& 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
890ostream& ostream::operator<<(const void *p)
891{ Is in osform.cc, to avoid pulling in all of _IO_vfprintf by this file. */ }
892#endif
893
894ostream& 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
919ostream::ostream(streambuf* sb, ostream* tied)
920{
921  init (sb, tied);
922}
923
924ostream& 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
932ostream& 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
940streampos 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
952ostream& ostream::flush()
953{
954    if (_strbuf->sync())
955	set(ios::badbit);
956    return *this;
957}
958
959ostream& flush(ostream& outs)
960{
961  return outs.flush();
962}
963
964istream& 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
984int 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
997ostream& ends(ostream& outs)
998{
999    outs.put('\0');
1000    return outs;
1001}
1002
1003ostream& endl(ostream& outs)
1004{
1005    return flush(outs.put('\n'));
1006}
1007
1008istream& lock(istream& ins)
1009{
1010  _IO_flockfile (ins._strbuf);
1011  return ins;
1012}
1013istream& unlock(istream& ins)
1014{
1015  _IO_funlockfile (ins._strbuf);
1016  return ins;
1017}
1018ostream& lock(ostream& outs)
1019{
1020  _IO_flockfile (outs._strbuf);
1021  return outs;
1022}
1023ostream& unlock(ostream& outs)
1024{
1025  _IO_funlockfile (outs._strbuf);
1026  return outs;
1027}
1028
1029
1030ostream& 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
1044ostream& ostream::write(const char *s, int n)
1045{
1046  return write((const char*)s, (streamsize)n);
1047}
1048ostream& ostream::write(const unsigned char *s, int n)
1049{
1050  return write((const char*)s, (streamsize)n);
1051}
1052ostream& ostream::write(const signed char *s, int n)
1053{
1054  return write((const char*)s, (streamsize)n);
1055}
1056ostream& ostream::write(const void *s, int n)
1057{
1058  return write((const char*)s, (streamsize)n);
1059}
1060
1061void 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
1071iostream::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
1079void 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
1089int 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