/*ident "@(#)cls4:lib/stream/out.c 1.5" */ /******************************************************************************* C++ source for the C++ Language System, Release 3.0. This product is a new release of the original cfront developed in the computer science research center of AT&T Bell Laboratories. Copyright (c) 1993 UNIX System Laboratories, Inc. Copyright (c) 1991, 1992 AT&T and UNIX System Laboratories, Inc. Copyright (c) 1984, 1989, 1990 AT&T. All Rights Reserved. THIS IS UNPUBLISHED PROPRIETARY SOURCE CODE of AT&T and UNIX System Laboratories, Inc. The copyright notice above does not evidence any actual or intended publication of such source code. *******************************************************************************/ #include #include "streamdefs.h" #include #define OSTREAM ostream const int basebits = ios::dec|ios::oct|ios::hex ; // At the cost of 100 bytes of table we can measurably speed // up conversion (at least on a VAX) static char digit1[] = { '0','1','2','3','4','5','6','7','8','9', '0','1','2','3','4','5','6','7','8','9', '0','1','2','3','4','5','6','7','8','9', '0','1','2','3','4','5','6','7','8','9', '0','1','2','3','4','5','6','7','8','9', '0','1','2','3','4','5','6','7','8','9', '0','1','2','3','4','5','6','7','8','9', '0','1','2','3','4','5','6','7','8','9', '0','1','2','3','4','5','6','7','8','9', '0','1','2','3','4','5','6','7','8','9', } ; static char digit2[] = { '0','0','0','0','0','0','0','0','0','0', '1','1','1','1','1','1','1','1','1','1', '2','2','2','2','2','2','2','2','2','2', '3','3','3','3','3','3','3','3','3','3', '4','4','4','4','4','4','4','4','4','4', '5','5','5','5','5','5','5','5','5','5', '6','6','6','6','6','6','6','6','6','6', '7','7','7','7','7','7','7','7','7','7', '8','8','8','8','8','8','8','8','8','8', '9','9','9','9','9','9','9','9','9','9', } ; static char* conv10(long i, char* bufend) /* p points to right end of a buffer. Function function returns * pointer to left end of converted number. Number is not 0 terminated. * * Special care with negatives to avoid problems with * biggest negative number on 2's complement machines */ { register long j = i ; register char* p = bufend ; /* Above entered low order digit or 0 if i is zero */ if ( j >= 0 ) { register int diff ; do { register long by100 = j/100 ; diff = (int)(j-100*by100) ; *p-- = digit1[diff] ; *p-- = digit2[diff] ; j = by100; } while ( j > 0 ) ; if ( diff<10 ) ++p ; //compensate for extra 0 } else { // j < 0 register int diff ; do { register long by100 = j/100 ; diff = (int)(100*by100-j) ; *p-- = digit1[diff] ; *p-- = digit2[diff] ; j = by100; } while ( j < 0 ) ; if ( diff<10 ) ++p ; //compensate for extra 0 } return p+1 ; } static char* uconv10(unsigned long i, char* bufend) /* Same interface as conv10 except unsigned so we don't have * to worry about negatives */ { register unsigned long j = i ; register char* p = bufend ; register int diff ; do { register long by100 = j/100 ; diff = (int)(j-100*by100) ; *p-- = digit1[diff] ; *p-- = digit2[diff] ; j = by100; } while ( j > 0 ) ; if ( diff<10 ) ++p ; //compensate for extra 0 return p+1 ; } static char* conv8(register unsigned long i, register char* p) { do { *p-- = (char)('0' + i%8) ; } while ( (i >>= 3) > 0 ) ; return p+1 ; } static char* conv16(register unsigned long i, register char* p) { do { register int dig = (int)(i%16) ; if ( dig < 10 ) *p-- = (char)('0' + i%16) ; else *p-- = (char)('a'-10 + dig) ; } while ( (i >>= 4) > 0 ) ; return p+1 ; } static char* conv16u(register unsigned long i, register char* p) { do { register int dig = (int)(i%16) ; if ( dig < 10 ) *p-- = (char)('0' + i%16) ; else *p-- = (char)('A'-10 + dig) ; } while ( (i >>= 4) > 0 ) ; return p+1 ; } ostream& OSTREAM::operator<<(const char* s) { // I play some games so that if BREAKEVEN is <= 0 all // tests get set the right way at compile time # if BREAKEVEN > 0 static int avglen = BREAKEVEN ; // running average of the lengths // of strings ; # else static const int avglen = BREAKEVEN ; // fixed constant so all tests // are fixed at compile time # endif register int fwidth = width(0) ; if (!opfx() ) return *this ; if ( s==0 ) return *this; register streambuf* nbp = bp ; register const char* p ; register int len ; register int pad ; register int leftjust = ( (flags()&left) != 0 ) ; if ( BREAKEVEN<0 || BREAKEVEN>0 && avglen<=BREAKEVEN && (fwidth==0 || leftjust)){ p = s ; while ( *p ) { if ( nbp->sputc(*p++) == EOF ) { setstate(badbit) ; break ; } } len = p-s ; pad = fwidth-len ; } else { len = strlen(s) ; pad = fwidth-len ; if ( pad>0 && !leftjust ) { while ( pad-- > 0 ) { if ( nbp->sputc(fill()) == EOF ) { setstate(badbit) ; } } } write(s,len) ; } if ( pad > 0 ) { while ( pad-- > 0 ) { if ( nbp->sputc(fill()) == EOF ) setstate(badbit) ; } } if ( BREAKEVEN > 0 ) { // will be eliminated at compile time avglen = (3*avglen + len) >> 2; } osfx() ; return *this; } static int dofield( ostream* ios, register char* pfx, int pwidth, register char* sfx, int swidth) { register streambuf* b = ios->rdbuf() ; register int w = ios->width(0)-(pwidth+swidth) ; register int f = (int)ios->flags() ; register int fchar = ios->fill() ; if ( (f&ios::right) || !(f&(ios::left|ios::internal)) ) { while ( w-- > 0 ) { if ( b->sputc(fchar) == EOF ) return ios::badbit ; } } while ( *pfx ) { if ( b->sputc(*pfx++) == EOF ) return ios::badbit ; } if ( f&ios::internal ) { while ( w-- > 0 ) { if ( b->sputc(fchar) == EOF ) return ios::badbit ; } } while ( *sfx ) { if ( b->sputc(*sfx++) == EOF ) return ios::badbit ; } while ( w-- > 0 ) { if ( b->sputc(fchar) == EOF ) return ios::badbit ; } return 0 ; } static const int dbufsize = 32 ; ostream& OSTREAM::operator<<(long i) { if (!opfx()) { width(0) ; return *this; } char buf[dbufsize]; register char *p ; register char* pfx = "" ; register int pfxsize = 0 ; buf[dbufsize-1] = 0 ; switch( flags()&basebits ) { case ios::oct : p = conv8(i,&buf[dbufsize-2]) ; if ( (flags()&showbase) ) { // && i removed pfx = "0" ; pfxsize = 1 ; } break ; case ios::hex : if ( flags()&uppercase ) { p=conv16u(i,&buf[dbufsize-2]); if ( flags()&showbase ) { pfx = "0X" ; pfxsize = 2 ; } } else { p=conv16(i,&buf[dbufsize-2]); if ( flags()&showbase ) { pfx = "0x" ; pfxsize = 2 ; } } break ; default: p = conv10(i,&buf[dbufsize-2]) ; if ( i < 0 ) { pfx = "-" ; pfxsize = 1 ; } else if ( flags()&showpos ) { pfx = "+" ; pfxsize = 1 ; } break ; } register int err ; if ( err = dofield(this,pfx,pfxsize,p,&buf[dbufsize-1]-p) ) { setstate(err) ; } osfx() ; return *this ; } ostream& OSTREAM::operator<<(unsigned long i) { if (!opfx()) { width(0) ; return *this; } char buf[dbufsize]; register char *p ; register char* pfx = "" ; register int pfxsize = 0 ; buf[dbufsize-1] = 0 ; switch( flags()&basebits ) { case ios::oct : p = conv8(i,&buf[dbufsize-2]) ; if ( (flags()&showbase) && i ) { pfx = "0" ; pfxsize = 1 ; } break ; case ios::hex : if ( flags()&uppercase ) { p=conv16u(i,&buf[dbufsize-2]); if ( flags()&showbase ) { pfx = "0X" ; pfxsize = 2 ; } } else { p=conv16(i,&buf[dbufsize-2]); if ( flags()&showbase ) { pfx = "0x" ; pfxsize = 2 ; } } break ; default: p = uconv10(i,&buf[dbufsize-2]) ; break ; } register int err ; if ( err = dofield(this,pfx,pfxsize,p,&buf[dbufsize-1]-p) ) { setstate(err) ; } osfx() ; return *this ; } ostream& OSTREAM::operator<<(register streambuf* b) { register streambuf* nbp = bp; register int c; if (!opfx()) return *this; if ( !b ) { setstate(failbit) ; return *this ; } c = b->sgetc(); while (c != EOF) { if (nbp->sputc(c) == EOF) { setstate(badbit) ; break; } c = b->snextc(); } osfx() ; return *this; } ostream& OSTREAM::operator<<( void* p) { long f = setf(ios::showbase|PTRBASE, basebits|ios::showbase) ; *this << (long)p ; setf(f,~0) ; return *this ; } /* add this later ostream& OSTREAM::operator<<( const void* p) { long f = setf(ios::showbase|PTRBASE, basebits|ios::showbase) ; *this << (long)p ; setf(f,~0) ; return *this ; } */ ostream& OSTREAM::operator<<(int x) { *this << (long)x ; return *this ; } ostream& OSTREAM::operator<<(unsigned int x) { *this << (unsigned long)x ; return *this ; } ostream& OSTREAM::complicated_put(char c) { if ( opfx() ) { if ( bp->sputc(c) == EOF ) { setstate(eofbit|failbit) ; } osfx() ; } return *this ; } ostream& OSTREAM::ls_complicated(char c) { put(c) ; osfx() ; return *this ; } ostream& OSTREAM::ls_complicated(unsigned char c) { put(c) ; osfx() ; return *this ; }