134226Sbostic /* 234233Sbostic * Copyright (c) 1988 Regents of the University of California. 334233Sbostic * All rights reserved. 434226Sbostic * 534233Sbostic * Redistribution and use in source and binary forms are permitted 634233Sbostic * provided that this notice is preserved and that due credit is given 734233Sbostic * to the University of California at Berkeley. The name of the University 834233Sbostic * may not be used to endorse or promote products derived from this 934233Sbostic * software without specific prior written permission. This software 1034233Sbostic * is provided ``as is'' without express or implied warranty. 1134226Sbostic */ 1234226Sbostic 1334233Sbostic #if defined(LIBC_SCCS) && !defined(lint) 14*34331Sbostic static char sccsid[] = "@(#)vfprintf.c 5.27 (Berkeley) 05/19/88"; 1534233Sbostic #endif /* LIBC_SCCS and not lint */ 1634233Sbostic 1734261Sbostic #include <sys/types.h> 1834233Sbostic #include <varargs.h> 1934226Sbostic #include <stdio.h> 2034233Sbostic #include <ctype.h> 2134226Sbostic 2234328Sbostic /* 11-bit exponent (VAX G floating point) is 308 decimal digits */ 2334328Sbostic #define MAXEXP 308 2434328Sbostic /* 128 bit fraction takes up 39 decimal digits; max reasonable precision */ 2534328Sbostic #define MAXFRACT 39 2634226Sbostic 2734328Sbostic #define BUF (MAXEXP+MAXFRACT+1) /* + decimal point */ 2834328Sbostic 2934323Sbostic #define PUTC(ch) {++cnt; putc((char)ch, fp);} 3034236Sbostic 3134318Sbostic #define ARG() \ 3234318Sbostic _ulong = flags&LONGINT ? va_arg(argp, long) : \ 3334318Sbostic flags&SHORTINT ? va_arg(argp, short) : va_arg(argp, int); 3434235Sbostic 35*34331Sbostic #define todigit(c) ((c) - '0') 36*34331Sbostic #define tochar(n) ((n) + '0') 37*34331Sbostic 3834318Sbostic /* have to deal with the negative buffer count kludge */ 3934318Sbostic #define NEGATIVE_COUNT_KLUDGE 4034318Sbostic 4134318Sbostic #define LONGINT 0x01 /* long integer */ 4234318Sbostic #define LONGDBL 0x02 /* long double; unimplemented */ 4334318Sbostic #define SHORTINT 0x04 /* short integer */ 4434318Sbostic #define ALT 0x08 /* alternate form */ 4534318Sbostic #define LADJUST 0x10 /* left adjustment */ 4634318Sbostic 4734323Sbostic _doprnt(fmt0, argp, fp) 4834323Sbostic u_char *fmt0; 4934233Sbostic va_list argp; 5034235Sbostic register FILE *fp; 5134226Sbostic { 5234323Sbostic register u_char *fmt; 5334323Sbostic register int ch, cnt, n; 5434323Sbostic register char *t; 5534235Sbostic double _double; 5634314Sbostic u_long _ulong; 5734328Sbostic int base, flags, fpprec, prec, size, width; 5834328Sbostic char padc, sign, *digs, buf[BUF], *_cvt(); 5934226Sbostic 6034323Sbostic fmt = fmt0; 6134243Sbostic digs = "0123456789abcdef"; 6234322Sbostic for (cnt = 0;; ++fmt) { 6334318Sbostic n = fp->_cnt; 6434318Sbostic for (t = fp->_ptr; (ch = *fmt) && ch != '%'; ++cnt, ++fmt) 6534318Sbostic if (--n < 0 6634318Sbostic #ifdef NEGATIVE_COUNT_KLUDGE 6734318Sbostic && (!(fp->_flag & _IOLBF) || -n >= fp->_bufsiz) 6834318Sbostic #endif 6934318Sbostic || ch == '\n' && fp->_flag&_IOLBF) { 7034318Sbostic fp->_cnt = n; 7134318Sbostic fp->_ptr = t; 7234318Sbostic (void)_flsbuf(ch, fp); 7334318Sbostic n = fp->_cnt; 7434318Sbostic t = fp->_ptr; 7534318Sbostic } 7634318Sbostic else 7734314Sbostic *t++ = ch; 7834318Sbostic fp->_cnt = n; 7934318Sbostic fp->_ptr = t; 8034318Sbostic if (!ch) 8134314Sbostic return(cnt); 8234314Sbostic 8334328Sbostic flags = fpprec = width = 0; 8434233Sbostic prec = -1; 8534233Sbostic padc = ' '; 8634318Sbostic sign = '\0'; 8734226Sbostic 8834318Sbostic rflag: switch (*++fmt) { 8934318Sbostic case ' ': 9034318Sbostic sign = ' '; 9134318Sbostic goto rflag; 9234233Sbostic case '#': 9334318Sbostic flags |= ALT; 9434318Sbostic goto rflag; 9534233Sbostic case '*': 9634235Sbostic /* 9734235Sbostic * ``A negative field width argument is taken as a 9834235Sbostic * - flag followed by a positive field width.'' 9934235Sbostic * -- ANSI X3J11 10034235Sbostic * They don't exclude field widths read from args. 10134235Sbostic */ 10234235Sbostic if ((width = va_arg(argp, int)) >= 0) 10334318Sbostic goto rflag; 10434235Sbostic width = -width; 10534235Sbostic /*FALLTHROUGH*/ 10634235Sbostic case '-': 10734318Sbostic flags |= LADJUST; 10834318Sbostic goto rflag; 10934233Sbostic case '+': 11034314Sbostic sign = '+'; 11134318Sbostic goto rflag; 11234233Sbostic case '.': 11334235Sbostic if (*++fmt == '*') 11434318Sbostic n = va_arg(argp, int); 11534318Sbostic else if (isascii(*fmt) && isdigit(*fmt)) { 11634318Sbostic n = 0; 11734233Sbostic do { 118*34331Sbostic n = 10 * n + todigit(*fmt); 11934318Sbostic } while (isascii(*++fmt) && isdigit(*fmt)); 12034233Sbostic --fmt; 12134226Sbostic } 12234235Sbostic else { 12334318Sbostic --fmt; 12434235Sbostic prec = 0; 12534318Sbostic goto rflag; 12634235Sbostic } 12734318Sbostic prec = n < 0 ? -1 : n; 12834318Sbostic goto rflag; 12934233Sbostic case '0': 13034233Sbostic padc = '0'; 13134235Sbostic /*FALLTHROUGH*/ 13234233Sbostic case '1': case '2': case '3': case '4': 13334233Sbostic case '5': case '6': case '7': case '8': case '9': 13434318Sbostic n = 0; 13534233Sbostic do { 136*34331Sbostic n = 10 * n + todigit(*fmt); 13734318Sbostic } while (isascii(*++fmt) && isdigit(*fmt)); 13834318Sbostic width = n; 13934233Sbostic --fmt; 14034319Sbostic goto rflag; 14134235Sbostic case 'L': 14234329Sbostic flags |= LONGDBL; 14334318Sbostic goto rflag; 14434235Sbostic case 'h': 14534318Sbostic flags |= SHORTINT; 14634318Sbostic goto rflag; 14734233Sbostic case 'l': 14834318Sbostic flags |= LONGINT; 14934318Sbostic goto rflag; 15034314Sbostic case 'c': 15134319Sbostic buf[0] = va_arg(argp, int); 15234314Sbostic size = 1; 15334319Sbostic t = buf; 15434314Sbostic goto pforw; 15534314Sbostic case 'd': 15634318Sbostic case 'i': 15734318Sbostic ARG(); 15834318Sbostic if ((long)_ulong < 0) { 15934318Sbostic _ulong = -_ulong; 16034314Sbostic sign = '-'; 16134241Sbostic } 16234241Sbostic base = 10; 16334327Sbostic goto number; 16434261Sbostic case 'e': 16534236Sbostic case 'E': 16634235Sbostic case 'f': 16734261Sbostic case 'g': 16834243Sbostic case 'G': 16934243Sbostic _double = va_arg(argp, double); 17034328Sbostic /* 17134328Sbostic * don't bother to do unrealistic precision; just 17234328Sbostic * pad it with zeroes later. This keeps buffer size 17334328Sbostic * rational. 17434328Sbostic */ 17534328Sbostic if (prec > MAXFRACT) { 17634328Sbostic fpprec = prec - MAXFRACT; 17734328Sbostic prec = MAXFRACT; 17834328Sbostic } 17934327Sbostic size = _cvt(_double, prec, flags, *fmt, padc, &sign, 18034323Sbostic buf, buf + sizeof(buf)) - buf; 18134319Sbostic t = buf; 18234327Sbostic /* 18334327Sbostic * zero-padded sign put out here; blank padded sign 18434327Sbostic * placed in number in _cvt(). 18534327Sbostic */ 18634327Sbostic if (sign && padc == '0') { 18734327Sbostic PUTC(sign); 18834327Sbostic --width; 18934327Sbostic } 19034314Sbostic goto pforw; 19134235Sbostic case 'n': 19234329Sbostic if (flags&LONGINT) 19334318Sbostic *va_arg(argp, long *) = cnt; 19434318Sbostic else if (flags&SHORTINT) 19534318Sbostic *va_arg(argp, short *) = cnt; 19634318Sbostic else 19734318Sbostic *va_arg(argp, int *) = cnt; 19834235Sbostic break; 19934226Sbostic case 'o': 20034318Sbostic ARG(); 20134226Sbostic base = 8; 20234327Sbostic goto nosign; 20334235Sbostic case 'p': 20434320Sbostic /* 20534321Sbostic * ``The argument shall be a pointer to void. The 20634321Sbostic * value of the pointer is converted to a sequence 20734321Sbostic * of printable characters, in an implementation- 20834321Sbostic * defined manner.'' 20934321Sbostic * -- ANSI X3J11 21034320Sbostic */ 21134327Sbostic /*NOSTRICT*/ 21234320Sbostic _ulong = (u_long)va_arg(argp, void *); 21334320Sbostic base = 16; 21434327Sbostic goto nosign; 21534226Sbostic case 's': 21634314Sbostic if (!(t = va_arg(argp, char *))) 21734314Sbostic t = "(null)"; 21834321Sbostic if (prec >= 0) { 21934321Sbostic /* 22034321Sbostic * can't use strlen; can only look for the 22134321Sbostic * NUL in the first `prec' characters, and 22234321Sbostic * strlen() will go further. 22334321Sbostic */ 22434321Sbostic char *p, *memchr(); 22534321Sbostic 22634321Sbostic if (p = memchr(t, 0, prec)) { 22734321Sbostic size = p - t; 22834321Sbostic if (size > prec) 22934321Sbostic size = prec; 23034321Sbostic } 23134321Sbostic else 23234321Sbostic size = prec; 23334321Sbostic } 23434321Sbostic else 23534321Sbostic size = strlen(t); 23634328Sbostic goto pforw; 23734226Sbostic case 'u': 23834318Sbostic ARG(); 23934226Sbostic base = 10; 24034327Sbostic goto nosign; 24134226Sbostic case 'X': 24234226Sbostic digs = "0123456789ABCDEF"; 24334233Sbostic /*FALLTHROUGH*/ 24434226Sbostic case 'x': 24534318Sbostic ARG(); 24634314Sbostic base = 16; 24734326Sbostic /* leading 0x/X only if non-zero */ 24834326Sbostic if (!_ulong) 24934324Sbostic flags &= ~ALT; 25034327Sbostic 25134327Sbostic /* unsigned conversions */ 25234327Sbostic nosign: sign = NULL; 25334326Sbostic /* 25434330Sbostic * ``... diouXx conversions ... if a precision is 25534330Sbostic * specified, the 0 flag will be ignored.'' 25634330Sbostic * -- ANSI X3J11 25734330Sbostic */ 25834330Sbostic number: if (prec >= 0) 25934330Sbostic padc = ' '; 26034330Sbostic /* 26134326Sbostic * ``The result of converting a zero value with an 26234326Sbostic * explicit precision of zero is no characters.'' 26334326Sbostic * -- ANSI X3J11 26434326Sbostic */ 26534330Sbostic if (!_ulong && !prec) { 26634330Sbostic size = 0; 26734330Sbostic goto pforw; 26834330Sbostic } 26934327Sbostic 27034328Sbostic t = buf + BUF - 1; 27134233Sbostic do { 27234314Sbostic *t-- = digs[_ulong % base]; 27334314Sbostic _ulong /= base; 27434314Sbostic } while(_ulong); 27534328Sbostic for (size = buf + BUF - 1 - t; size < prec; ++size) 27634324Sbostic *t-- = '0'; 27734328Sbostic digs = "0123456789abcdef"; 27834327Sbostic 27934327Sbostic /* alternate mode for hex and octal numbers */ 28034324Sbostic if (flags&ALT) 28134324Sbostic switch (base) { 28234324Sbostic case 16: 28334324Sbostic /* avoid "00000x35" */ 28434327Sbostic if (padc == ' ') { 28534327Sbostic *t-- = *fmt; 28634327Sbostic *t-- = '0'; 28734328Sbostic size += 2; 28834327Sbostic } 28934327Sbostic else { 29034324Sbostic PUTC('0'); 29134324Sbostic PUTC(*fmt); 29234328Sbostic width -= 2; 29334324Sbostic } 29434324Sbostic break; 29534324Sbostic case 8: 29634324Sbostic if (t[1] != '0') { 29734324Sbostic *t-- = '0'; 29834328Sbostic ++size; 29934324Sbostic } 30034324Sbostic break; 30134314Sbostic } 30234327Sbostic 30334327Sbostic if (sign) { 30434327Sbostic /* avoid "0000-3" */ 30534328Sbostic if (padc == ' ') { 30634327Sbostic *t-- = sign; 30734328Sbostic ++size; 30834328Sbostic } 30934328Sbostic else { 31034327Sbostic PUTC(sign); 31134328Sbostic --width; 31234328Sbostic } 31334327Sbostic } 31434328Sbostic ++t; 31534327Sbostic 31634328Sbostic pforw: if (!(flags&LADJUST) && width) 31734328Sbostic for (n = size + fpprec; n++ < width;) 31834263Sbostic PUTC(padc); 31934328Sbostic if (fp->_cnt - (n = size) >= 0) { 32034328Sbostic cnt += n; 32134328Sbostic fp->_cnt -= n; 32234328Sbostic bcopy(t, fp->_ptr, n); 32334328Sbostic fp->_ptr += n; 32434328Sbostic } 32534328Sbostic else for (; n--; ++t) 32634314Sbostic PUTC(*t); 32734328Sbostic while (fpprec--) 32834328Sbostic PUTC('0'); 32934328Sbostic if (flags&LADJUST) 33034328Sbostic for (n = size + fpprec; ++n < width;) 33134328Sbostic PUTC(' '); 33234226Sbostic break; 33334233Sbostic case '\0': /* "%?" prints ?, unless ? is NULL */ 33434314Sbostic return(cnt); 33534226Sbostic default: 33634263Sbostic PUTC(*fmt); 33734226Sbostic } 33834226Sbostic } 33934314Sbostic /*NOTREACHED*/ 34034226Sbostic } 34134242Sbostic 34234261Sbostic #define EFORMAT 0x01 34334261Sbostic #define FFORMAT 0x02 34434261Sbostic #define GFORMAT 0x04 34534314Sbostic #define DEFPREC 6 34634261Sbostic 34734323Sbostic static char * 34834327Sbostic _cvt(number, prec, flags, fmtch, padc, sign, startp, endp) 34934242Sbostic double number; 35034261Sbostic register int prec; 35134323Sbostic int flags; 35234323Sbostic u_char fmtch; 35334327Sbostic char padc, *sign, *startp, *endp; 35434242Sbostic { 355*34331Sbostic register char *p, *t; 35634261Sbostic register int expcnt, format; 35734248Sbostic double fract, integer, tmp, modf(); 35834261Sbostic int decpt; 359*34331Sbostic char *savep, exponent[MAXEXP]; 36034242Sbostic 36134314Sbostic if (prec == -1) 36234242Sbostic prec = DEFPREC; 36334242Sbostic 36434314Sbostic if (number < 0) { 36534327Sbostic *sign = '-'; 36634248Sbostic number = -number; 36734248Sbostic } 36834242Sbostic 36934327Sbostic /* if blank padded, add sign in as part of the number */ 37034327Sbostic if (*sign && padc == ' ') 37134327Sbostic *startp++ = *sign; 37234327Sbostic 37334261Sbostic switch(fmtch) { 37434261Sbostic case 'e': 37534261Sbostic case 'E': 37634261Sbostic format = EFORMAT; 37734261Sbostic break; 37834261Sbostic case 'f': 37934261Sbostic format = FFORMAT; 38034261Sbostic break; 38134261Sbostic case 'g': 38234261Sbostic case 'G': 38334261Sbostic format = GFORMAT; 38434261Sbostic fmtch -= 2; 38534261Sbostic } 38634261Sbostic 38734248Sbostic /* 38834248Sbostic * if the alternate flag is set, or, at least one digit of precision 38934248Sbostic * was requested, add a decimal point, unless it's the g/G format 39034314Sbostic * in which case we require two digits of precision, as it counts 39134248Sbostic * precision differently. 39234248Sbostic */ 39334318Sbostic decpt = flags&ALT || prec > (format&GFORMAT ? 1 : 0); 39434248Sbostic 39534248Sbostic expcnt = 0; 39634323Sbostic p = endp - 1; 39734248Sbostic fract = modf(number, &integer); 39834248Sbostic if (integer) { 39934248Sbostic /* get integer part of number; count decimal places */ 40034248Sbostic for (; integer; ++expcnt) { 40134248Sbostic tmp = modf(integer / 10, &integer); 402*34331Sbostic *p-- = tochar((int)((tmp + .03) * 10)); 40334242Sbostic } 40434248Sbostic 40534248Sbostic /* copy, in reverse order, to start of buffer */ 406*34331Sbostic t = startp; 407*34331Sbostic *t++ = *++p; 40834248Sbostic 40934248Sbostic /* 41034248Sbostic * if the format is g/G, and the resulting exponent will be 41134248Sbostic * greater than the precision, use e/E format. If e/E format, 41234248Sbostic * put in a decimal point as needed, and decrement precision 41334248Sbostic * count for each digit after the decimal point. 41434248Sbostic */ 41534248Sbostic if (format&GFORMAT && expcnt - 1 > prec || format&EFORMAT) { 41634248Sbostic if (format&GFORMAT) { 41734248Sbostic format |= EFORMAT; 41834248Sbostic 41934248Sbostic /* first digit is precision for g/G format */ 42034248Sbostic if (prec) 42134248Sbostic --prec; 42234248Sbostic } 42334248Sbostic if (decpt) 424*34331Sbostic *t++ = '.'; 425*34331Sbostic for (; ++p < endp && prec; --prec, *t++ = *p); 42634248Sbostic 42734318Sbostic /* precision ran out, round */ 42834248Sbostic if (p < endp) { 42934248Sbostic if (*p > '4') { 430*34331Sbostic for (savep = t--;; *t-- = '0') { 431*34331Sbostic if (*t == '.') 432*34331Sbostic --t; 433*34331Sbostic if (++*t <= '9') 43434248Sbostic break; 43534248Sbostic } 436*34331Sbostic t = savep; 43734248Sbostic } 43834248Sbostic fract = 0; 43934248Sbostic } 44034242Sbostic } 44134248Sbostic /* 44234314Sbostic * g/G in f format; if out of precision, replace digits with 44334314Sbostic * zeroes, note, have to round first. 44434248Sbostic */ 44534248Sbostic else if (format&GFORMAT) { 446*34331Sbostic for (; ++p < endp && prec; --prec, *t++ = *p); 44734248Sbostic /* precision ran out; round and then add zeroes */ 44834248Sbostic if (p < endp) { 44934248Sbostic if (*p > '4') { 450*34331Sbostic for (savep = t--; ++*t > '9'; 451*34331Sbostic *t-- = '0'); 452*34331Sbostic t = savep; 45334248Sbostic } 45434248Sbostic do { 455*34331Sbostic *t++ = '0'; 45634248Sbostic } while (++p < endp); 45734248Sbostic fract = 0; 45834248Sbostic } 45934248Sbostic if (decpt) 460*34331Sbostic *t++ = '.'; 46134242Sbostic } 46234248Sbostic /* f format */ 46334248Sbostic else { 464*34331Sbostic for (; ++p < endp; *t++ = *p); 46534248Sbostic if (decpt) 466*34331Sbostic *t++ = '.'; 46734248Sbostic } 468*34331Sbostic p = t; 46934248Sbostic } 47034248Sbostic /* 47134318Sbostic * if no fraction, the number was zero, and if no precision, can't 47234318Sbostic * show anything after the decimal point. 47334248Sbostic */ 47434248Sbostic else if (!fract || !prec) { 47534248Sbostic *startp++ = '0'; 47634318Sbostic if (decpt && !(format&GFORMAT)) 47734248Sbostic *startp++ = '.'; 47834318Sbostic *startp = '\0'; 47934323Sbostic return(startp); 48034248Sbostic } 48134248Sbostic /* 48234248Sbostic * if the format is g/G, and the resulting exponent will be less than 48334248Sbostic * -4 use e/E format. If e/E format, compute exponent value. 48434248Sbostic */ 48534248Sbostic else if (format&GFORMAT && fract < .0001 || format&EFORMAT) { 48634248Sbostic format |= EFORMAT; 48734248Sbostic if (fract) 48834248Sbostic for (p = startp; fract;) { 48934248Sbostic fract = modf(fract * 10, &tmp); 49034248Sbostic if (!tmp) { 49134248Sbostic --expcnt; 49234248Sbostic continue; 49334248Sbostic } 494*34331Sbostic *p++ = tochar((int)tmp); 49534248Sbostic break; 49634248Sbostic } 49734242Sbostic else 49834248Sbostic *p++ = '0'; 49934248Sbostic 50034248Sbostic /* g/G format, decrement precision for first digit */ 50134248Sbostic if (format&GFORMAT && prec) 50234248Sbostic --prec; 50334248Sbostic 50434248Sbostic /* add decimal after first non-zero digit */ 50534248Sbostic if (decpt) 50634248Sbostic *p++ = '.'; 50734242Sbostic } 50834248Sbostic /* 50934248Sbostic * f format or g/G printed as f format; don't worry about decimal 51034248Sbostic * point, if g/G format doesn't need it, will get stripped later. 51134248Sbostic */ 51234242Sbostic else { 51334248Sbostic p = startp; 51434248Sbostic *p++ = '0'; 51534248Sbostic *p++ = '.'; 51634248Sbostic } 51734248Sbostic 51834319Sbostic /* finish out requested precision */ 51934319Sbostic while (fract && prec-- > 0) { 52034319Sbostic fract = modf(fract * 10, &tmp); 521*34331Sbostic *p++ = tochar((int)tmp); 52234319Sbostic } 52334319Sbostic while (prec-- > 0) 52434319Sbostic *p++ = '0'; 52534248Sbostic 52634248Sbostic /* 52734248Sbostic * if any fractional value left, "round" it back up to the beginning 52834248Sbostic * of the number, fixing the exponent as necessary, and avoiding the 52934248Sbostic * decimal point. 53034248Sbostic */ 53134248Sbostic if (fract) { 53234248Sbostic (void)modf(fract * 10, &tmp); 53334248Sbostic if (tmp > 4) { 53434248Sbostic for (savep = p--;; *p-- = '0') { 53534248Sbostic if (*p == '.') 53634248Sbostic --p; 53734248Sbostic if (p == startp) { 53834248Sbostic *p = '1'; 53934248Sbostic ++expcnt; 54034248Sbostic break; 54134248Sbostic } 54234248Sbostic if (++*p <= '9') 54334248Sbostic break; 54434242Sbostic } 54534248Sbostic p = savep; 54634242Sbostic } 54734248Sbostic } 54834248Sbostic 54934248Sbostic /* 55034248Sbostic * if a g/G format and not alternate flag, lose trailing zeroes, 55134248Sbostic * if e/E or g/G format, and last char is decimal point, lose it. 55234248Sbostic */ 55334318Sbostic if (!(flags&ALT)) { 55434248Sbostic if (format&GFORMAT) 55534248Sbostic for (; p[-1] == '0'; --p); 55634248Sbostic if (format&(GFORMAT|EFORMAT) && p[-1] == '.') 55734248Sbostic --p; 55834248Sbostic } 55934248Sbostic 56034248Sbostic /* if an e/E format, add exponent */ 56134248Sbostic if (format&EFORMAT) { 56234248Sbostic *p++ = fmtch; 56334248Sbostic if (--expcnt < 0) { 56434248Sbostic expcnt = -expcnt; 56534248Sbostic *p++ = '-'; 56634242Sbostic } 56734248Sbostic else 56834248Sbostic *p++ = '+'; 569*34331Sbostic t = exponent + MAXEXP; 570*34331Sbostic if (expcnt > 9) { 571*34331Sbostic do { 572*34331Sbostic *--t = tochar(expcnt % 10); 573*34331Sbostic } while ((expcnt /= 10) > 9); 574*34331Sbostic *--t = tochar(expcnt); 575*34331Sbostic for (; t < exponent + MAXEXP; *p++ = *t++); 576*34331Sbostic } 577*34331Sbostic else { 578*34331Sbostic *p++ = '0'; 579*34331Sbostic *p++ = tochar(expcnt); 580*34331Sbostic } 58134242Sbostic } 58234323Sbostic return(p); 58334242Sbostic } 584