Commit | Line | Data |
---|---|---|
ad0e16d0 | 1 | /* |
5f6de66c KB |
2 | * Copyright (c) 1988 Regents of the University of California. |
3 | * All rights reserved. | |
ad0e16d0 | 4 | * |
5f6de66c KB |
5 | * Redistribution and use in source and binary forms are permitted |
6 | * provided that this notice is preserved and that due credit is given | |
7 | * to the University of California at Berkeley. The name of the University | |
8 | * may not be used to endorse or promote products derived from this | |
9 | * software without specific prior written permission. This software | |
10 | * is provided ``as is'' without express or implied warranty. | |
ad0e16d0 KB |
11 | */ |
12 | ||
5f6de66c | 13 | #if defined(LIBC_SCCS) && !defined(lint) |
95a39ea1 | 14 | static char sccsid[] = "@(#)vfprintf.c 5.24 (Berkeley) %G%"; |
5f6de66c | 15 | #endif /* LIBC_SCCS and not lint */ |
ad0e16d0 | 16 | |
0d15d742 | 17 | #include <sys/types.h> |
5f6de66c KB |
18 | #include <varargs.h> |
19 | #include <stdio.h> | |
20 | #include <ctype.h> | |
ad0e16d0 | 21 | |
95a39ea1 KB |
22 | /* 11-bit exponent (VAX G floating point) is 308 decimal digits */ |
23 | #define MAXEXP 308 | |
24 | /* 128 bit fraction takes up 39 decimal digits; max reasonable precision */ | |
25 | #define MAXFRACT 39 | |
26 | ||
27 | #define BUF (MAXEXP+MAXFRACT+1) /* + decimal point */ | |
6c1ffc8c | 28 | |
ef9c9d35 | 29 | #define PUTC(ch) {++cnt; putc((char)ch, fp);} |
66d7f790 | 30 | |
410bd0d3 KB |
31 | #define ARG() \ |
32 | _ulong = flags&LONGINT ? va_arg(argp, long) : \ | |
33 | flags&SHORTINT ? va_arg(argp, short) : va_arg(argp, int); | |
34 | ||
35 | /* have to deal with the negative buffer count kludge */ | |
36 | #define NEGATIVE_COUNT_KLUDGE | |
37 | ||
38 | #define LONGINT 0x01 /* long integer */ | |
39 | #define LONGDBL 0x02 /* long double; unimplemented */ | |
40 | #define SHORTINT 0x04 /* short integer */ | |
41 | #define ALT 0x08 /* alternate form */ | |
42 | #define LADJUST 0x10 /* left adjustment */ | |
ad0e16d0 | 43 | |
ef9c9d35 KB |
44 | _doprnt(fmt0, argp, fp) |
45 | u_char *fmt0; | |
5f6de66c | 46 | va_list argp; |
66d7f790 | 47 | register FILE *fp; |
ad0e16d0 | 48 | { |
ef9c9d35 KB |
49 | register u_char *fmt; |
50 | register int ch, cnt, n; | |
51 | register char *t; | |
66d7f790 | 52 | double _double; |
40233183 | 53 | u_long _ulong; |
95a39ea1 KB |
54 | int base, flags, fpprec, prec, size, width; |
55 | char padc, sign, *digs, buf[BUF], *_cvt(); | |
5f6de66c | 56 | |
ef9c9d35 | 57 | fmt = fmt0; |
5592524e | 58 | digs = "0123456789abcdef"; |
65942971 | 59 | for (cnt = 0;; ++fmt) { |
410bd0d3 KB |
60 | n = fp->_cnt; |
61 | for (t = fp->_ptr; (ch = *fmt) && ch != '%'; ++cnt, ++fmt) | |
62 | if (--n < 0 | |
63 | #ifdef NEGATIVE_COUNT_KLUDGE | |
64 | && (!(fp->_flag & _IOLBF) || -n >= fp->_bufsiz) | |
65 | #endif | |
66 | || ch == '\n' && fp->_flag&_IOLBF) { | |
67 | fp->_cnt = n; | |
68 | fp->_ptr = t; | |
69 | (void)_flsbuf(ch, fp); | |
70 | n = fp->_cnt; | |
71 | t = fp->_ptr; | |
40233183 | 72 | } |
410bd0d3 KB |
73 | else |
74 | *t++ = ch; | |
75 | fp->_cnt = n; | |
76 | fp->_ptr = t; | |
77 | if (!ch) | |
40233183 | 78 | return(cnt); |
ad0e16d0 | 79 | |
95a39ea1 | 80 | flags = fpprec = width = 0; |
5f6de66c KB |
81 | prec = -1; |
82 | padc = ' '; | |
410bd0d3 | 83 | sign = '\0'; |
5f6de66c | 84 | |
410bd0d3 KB |
85 | rflag: switch (*++fmt) { |
86 | case ' ': | |
87 | sign = ' '; | |
88 | goto rflag; | |
5f6de66c | 89 | case '#': |
410bd0d3 KB |
90 | flags |= ALT; |
91 | goto rflag; | |
5f6de66c | 92 | case '*': |
66d7f790 KB |
93 | /* |
94 | * ``A negative field width argument is taken as a | |
95 | * - flag followed by a positive field width.'' | |
96 | * -- ANSI X3J11 | |
97 | * They don't exclude field widths read from args. | |
98 | */ | |
99 | if ((width = va_arg(argp, int)) >= 0) | |
410bd0d3 | 100 | goto rflag; |
66d7f790 KB |
101 | width = -width; |
102 | /*FALLTHROUGH*/ | |
103 | case '-': | |
410bd0d3 KB |
104 | flags |= LADJUST; |
105 | goto rflag; | |
5f6de66c | 106 | case '+': |
40233183 | 107 | sign = '+'; |
410bd0d3 | 108 | goto rflag; |
5f6de66c | 109 | case '.': |
66d7f790 | 110 | if (*++fmt == '*') |
410bd0d3 KB |
111 | n = va_arg(argp, int); |
112 | else if (isascii(*fmt) && isdigit(*fmt)) { | |
113 | n = 0; | |
5f6de66c | 114 | do { |
410bd0d3 KB |
115 | n = 10 * n + *fmt - '0'; |
116 | } while (isascii(*++fmt) && isdigit(*fmt)); | |
5f6de66c | 117 | --fmt; |
ad0e16d0 | 118 | } |
66d7f790 | 119 | else { |
66d7f790 | 120 | --fmt; |
410bd0d3 KB |
121 | prec = 0; |
122 | goto rflag; | |
66d7f790 | 123 | } |
410bd0d3 KB |
124 | prec = n < 0 ? -1 : n; |
125 | goto rflag; | |
5f6de66c KB |
126 | case '0': |
127 | padc = '0'; | |
66d7f790 | 128 | /*FALLTHROUGH*/ |
5f6de66c KB |
129 | case '1': case '2': case '3': case '4': |
130 | case '5': case '6': case '7': case '8': case '9': | |
410bd0d3 | 131 | n = 0; |
5f6de66c | 132 | do { |
410bd0d3 KB |
133 | n = 10 * n + *fmt - '0'; |
134 | } while (isascii(*++fmt) && isdigit(*fmt)); | |
135 | width = n; | |
5f6de66c | 136 | --fmt; |
aa876f9d | 137 | goto rflag; |
66d7f790 | 138 | case 'L': |
410bd0d3 KB |
139 | /* |
140 | * C doesn't have a long double; use long for now. | |
141 | * flags |= LONGDBL; | |
142 | */ | |
143 | flags |= LONGINT; | |
144 | goto rflag; | |
66d7f790 | 145 | case 'h': |
410bd0d3 KB |
146 | flags |= SHORTINT; |
147 | goto rflag; | |
5f6de66c | 148 | case 'l': |
410bd0d3 KB |
149 | flags |= LONGINT; |
150 | goto rflag; | |
40233183 | 151 | case 'c': |
aa876f9d | 152 | buf[0] = va_arg(argp, int); |
40233183 | 153 | size = 1; |
aa876f9d | 154 | t = buf; |
40233183 | 155 | goto pforw; |
a5676d90 | 156 | case 'd': |
410bd0d3 KB |
157 | case 'i': |
158 | ARG(); | |
159 | if ((long)_ulong < 0) { | |
160 | _ulong = -_ulong; | |
40233183 | 161 | sign = '-'; |
a5676d90 | 162 | } |
a5676d90 | 163 | base = 10; |
bb5070be | 164 | goto number; |
6c1ffc8c | 165 | case 'e': |
0d15d742 | 166 | case 'E': |
66d7f790 | 167 | case 'f': |
5592524e | 168 | case 'g': |
0d15d742 | 169 | case 'G': |
5592524e | 170 | _double = va_arg(argp, double); |
95a39ea1 KB |
171 | /* |
172 | * don't bother to do unrealistic precision; just | |
173 | * pad it with zeroes later. This keeps buffer size | |
174 | * rational. | |
175 | */ | |
176 | if (prec > MAXFRACT) { | |
177 | fpprec = prec - MAXFRACT; | |
178 | prec = MAXFRACT; | |
179 | } | |
bb5070be | 180 | size = _cvt(_double, prec, flags, *fmt, padc, &sign, |
ef9c9d35 | 181 | buf, buf + sizeof(buf)) - buf; |
aa876f9d | 182 | t = buf; |
bb5070be KB |
183 | /* |
184 | * zero-padded sign put out here; blank padded sign | |
185 | * placed in number in _cvt(). | |
186 | */ | |
187 | if (sign && padc == '0') { | |
188 | PUTC(sign); | |
189 | --width; | |
190 | } | |
40233183 | 191 | goto pforw; |
66d7f790 | 192 | case 'n': |
410bd0d3 KB |
193 | if (flags&LONGDBL || flags&LONGINT) |
194 | *va_arg(argp, long *) = cnt; | |
195 | else if (flags&SHORTINT) | |
196 | *va_arg(argp, short *) = cnt; | |
197 | else | |
198 | *va_arg(argp, int *) = cnt; | |
66d7f790 | 199 | break; |
ad0e16d0 | 200 | case 'o': |
410bd0d3 | 201 | ARG(); |
ad0e16d0 | 202 | base = 8; |
bb5070be | 203 | goto nosign; |
66d7f790 | 204 | case 'p': |
2c71023f | 205 | /* |
c748d653 KB |
206 | * ``The argument shall be a pointer to void. The |
207 | * value of the pointer is converted to a sequence | |
208 | * of printable characters, in an implementation- | |
209 | * defined manner.'' | |
210 | * -- ANSI X3J11 | |
2c71023f | 211 | */ |
bb5070be | 212 | /*NOSTRICT*/ |
2c71023f KB |
213 | _ulong = (u_long)va_arg(argp, void *); |
214 | base = 16; | |
bb5070be | 215 | goto nosign; |
ad0e16d0 | 216 | case 's': |
40233183 KB |
217 | if (!(t = va_arg(argp, char *))) |
218 | t = "(null)"; | |
c748d653 KB |
219 | if (prec >= 0) { |
220 | /* | |
221 | * can't use strlen; can only look for the | |
222 | * NUL in the first `prec' characters, and | |
223 | * strlen() will go further. | |
224 | */ | |
225 | char *p, *memchr(); | |
226 | ||
227 | if (p = memchr(t, 0, prec)) { | |
228 | size = p - t; | |
229 | if (size > prec) | |
230 | size = prec; | |
231 | } | |
232 | else | |
233 | size = prec; | |
234 | } | |
235 | else | |
236 | size = strlen(t); | |
95a39ea1 | 237 | goto pforw; |
ad0e16d0 | 238 | case 'u': |
410bd0d3 | 239 | ARG(); |
ad0e16d0 | 240 | base = 10; |
bb5070be | 241 | goto nosign; |
ad0e16d0 KB |
242 | case 'X': |
243 | digs = "0123456789ABCDEF"; | |
5f6de66c | 244 | /*FALLTHROUGH*/ |
ad0e16d0 | 245 | case 'x': |
410bd0d3 | 246 | ARG(); |
40233183 | 247 | base = 16; |
8a91f8d6 KB |
248 | /* leading 0x/X only if non-zero */ |
249 | if (!_ulong) | |
ed76755f | 250 | flags &= ~ALT; |
bb5070be KB |
251 | |
252 | /* unsigned conversions */ | |
253 | nosign: sign = NULL; | |
8a91f8d6 KB |
254 | /* |
255 | * ``The result of converting a zero value with an | |
256 | * explicit precision of zero is no characters.'' | |
257 | * -- ANSI X3J11 | |
258 | */ | |
bb5070be | 259 | number: if (!_ulong && !prec) |
8a91f8d6 | 260 | break; |
bb5070be | 261 | |
95a39ea1 | 262 | t = buf + BUF - 1; |
5f6de66c | 263 | do { |
40233183 KB |
264 | *t-- = digs[_ulong % base]; |
265 | _ulong /= base; | |
266 | } while(_ulong); | |
95a39ea1 | 267 | for (size = buf + BUF - 1 - t; size < prec; ++size) |
ed76755f | 268 | *t-- = '0'; |
95a39ea1 | 269 | digs = "0123456789abcdef"; |
bb5070be KB |
270 | |
271 | /* alternate mode for hex and octal numbers */ | |
ed76755f KB |
272 | if (flags&ALT) |
273 | switch (base) { | |
274 | case 16: | |
275 | /* avoid "00000x35" */ | |
bb5070be | 276 | if (padc == ' ') { |
ed76755f KB |
277 | *t-- = *fmt; |
278 | *t-- = '0'; | |
95a39ea1 | 279 | size += 2; |
ed76755f | 280 | } |
bb5070be KB |
281 | else { |
282 | PUTC('0'); | |
283 | PUTC(*fmt); | |
95a39ea1 | 284 | width -= 2; |
bb5070be | 285 | } |
ed76755f KB |
286 | break; |
287 | case 8: | |
288 | if (t[1] != '0') { | |
289 | *t-- = '0'; | |
95a39ea1 | 290 | ++size; |
ed76755f KB |
291 | } |
292 | break; | |
40233183 | 293 | } |
bb5070be KB |
294 | |
295 | if (sign) { | |
296 | /* avoid "0000-3" */ | |
95a39ea1 | 297 | if (padc == ' ') { |
bb5070be | 298 | *t-- = sign; |
95a39ea1 KB |
299 | ++size; |
300 | } | |
301 | else { | |
bb5070be | 302 | PUTC(sign); |
95a39ea1 KB |
303 | --width; |
304 | } | |
bb5070be | 305 | } |
95a39ea1 | 306 | ++t; |
bb5070be | 307 | |
95a39ea1 KB |
308 | pforw: if (!(flags&LADJUST) && width) |
309 | for (n = size + fpprec; n++ < width;) | |
f853d467 | 310 | PUTC(padc); |
95a39ea1 KB |
311 | if (fp->_cnt - (n = size) >= 0) { |
312 | cnt += n; | |
313 | fp->_cnt -= n; | |
314 | bcopy(t, fp->_ptr, n); | |
315 | fp->_ptr += n; | |
316 | } | |
317 | else for (; n--; ++t) | |
40233183 | 318 | PUTC(*t); |
95a39ea1 KB |
319 | while (fpprec--) |
320 | PUTC('0'); | |
321 | if (flags&LADJUST) | |
322 | for (n = size + fpprec; ++n < width;) | |
323 | PUTC(' '); | |
ad0e16d0 | 324 | break; |
5f6de66c | 325 | case '\0': /* "%?" prints ?, unless ? is NULL */ |
40233183 | 326 | return(cnt); |
ad0e16d0 | 327 | default: |
f853d467 | 328 | PUTC(*fmt); |
ad0e16d0 | 329 | } |
ad0e16d0 | 330 | } |
40233183 | 331 | /*NOTREACHED*/ |
ad0e16d0 | 332 | } |
cd0a25f4 | 333 | |
0d15d742 KB |
334 | #define EFORMAT 0x01 |
335 | #define FFORMAT 0x02 | |
336 | #define GFORMAT 0x04 | |
40233183 | 337 | #define DEFPREC 6 |
0d15d742 | 338 | |
ef9c9d35 | 339 | static char * |
bb5070be | 340 | _cvt(number, prec, flags, fmtch, padc, sign, startp, endp) |
cd0a25f4 | 341 | double number; |
0d15d742 | 342 | register int prec; |
ef9c9d35 KB |
343 | int flags; |
344 | u_char fmtch; | |
bb5070be | 345 | char padc, *sign, *startp, *endp; |
cd0a25f4 | 346 | { |
862bbfbe | 347 | register char *p; |
0d15d742 | 348 | register int expcnt, format; |
862bbfbe | 349 | double fract, integer, tmp, modf(); |
0d15d742 | 350 | int decpt; |
ef9c9d35 | 351 | char *savep; |
cd0a25f4 | 352 | |
40233183 | 353 | if (prec == -1) |
cd0a25f4 | 354 | prec = DEFPREC; |
cd0a25f4 | 355 | |
40233183 | 356 | if (number < 0) { |
bb5070be | 357 | *sign = '-'; |
862bbfbe KB |
358 | number = -number; |
359 | } | |
bb5070be KB |
360 | |
361 | /* if blank padded, add sign in as part of the number */ | |
362 | if (*sign && padc == ' ') | |
363 | *startp++ = *sign; | |
862bbfbe | 364 | |
0d15d742 KB |
365 | switch(fmtch) { |
366 | case 'e': | |
367 | case 'E': | |
368 | format = EFORMAT; | |
369 | break; | |
370 | case 'f': | |
371 | format = FFORMAT; | |
372 | break; | |
373 | case 'g': | |
374 | case 'G': | |
375 | format = GFORMAT; | |
376 | fmtch -= 2; | |
377 | } | |
378 | ||
862bbfbe KB |
379 | /* |
380 | * if the alternate flag is set, or, at least one digit of precision | |
381 | * was requested, add a decimal point, unless it's the g/G format | |
40233183 | 382 | * in which case we require two digits of precision, as it counts |
862bbfbe KB |
383 | * precision differently. |
384 | */ | |
410bd0d3 | 385 | decpt = flags&ALT || prec > (format&GFORMAT ? 1 : 0); |
cd0a25f4 | 386 | |
862bbfbe | 387 | expcnt = 0; |
ef9c9d35 | 388 | p = endp - 1; |
862bbfbe KB |
389 | fract = modf(number, &integer); |
390 | if (integer) { | |
391 | register char *p2; | |
392 | ||
393 | /* get integer part of number; count decimal places */ | |
394 | for (; integer; ++expcnt) { | |
395 | tmp = modf(integer / 10, &integer); | |
396 | *p-- = (int)((tmp + .03) * 10) + '0'; | |
cd0a25f4 | 397 | } |
862bbfbe KB |
398 | |
399 | /* copy, in reverse order, to start of buffer */ | |
400 | p2 = startp; | |
401 | *p2++ = *++p; | |
402 | ||
403 | /* | |
404 | * if the format is g/G, and the resulting exponent will be | |
405 | * greater than the precision, use e/E format. If e/E format, | |
406 | * put in a decimal point as needed, and decrement precision | |
407 | * count for each digit after the decimal point. | |
408 | */ | |
409 | if (format&GFORMAT && expcnt - 1 > prec || format&EFORMAT) { | |
410 | if (format&GFORMAT) { | |
411 | format |= EFORMAT; | |
412 | ||
413 | /* first digit is precision for g/G format */ | |
414 | if (prec) | |
415 | --prec; | |
416 | } | |
417 | if (decpt) | |
418 | *p2++ = '.'; | |
419 | for (; ++p < endp && prec; --prec, *p2++ = *p); | |
420 | ||
410bd0d3 | 421 | /* precision ran out, round */ |
862bbfbe KB |
422 | if (p < endp) { |
423 | if (*p > '4') { | |
424 | for (savep = p2--;; *p2-- = '0') { | |
425 | if (*p2 == '.') | |
426 | --p2; | |
427 | if (++*p2 <= '9') | |
428 | break; | |
429 | } | |
430 | p2 = savep; | |
431 | } | |
432 | fract = 0; | |
433 | } | |
434 | } | |
435 | /* | |
40233183 KB |
436 | * g/G in f format; if out of precision, replace digits with |
437 | * zeroes, note, have to round first. | |
862bbfbe KB |
438 | */ |
439 | else if (format&GFORMAT) { | |
440 | for (; ++p < endp && prec; --prec, *p2++ = *p); | |
441 | /* precision ran out; round and then add zeroes */ | |
442 | if (p < endp) { | |
443 | if (*p > '4') { | |
444 | for (savep = p2--; ++*p2 > '9'; | |
445 | *p2-- = '0'); | |
446 | p2 = savep; | |
447 | } | |
448 | do { | |
449 | *p2++ = '0'; | |
450 | } while (++p < endp); | |
451 | fract = 0; | |
452 | } | |
453 | if (decpt) | |
454 | *p2++ = '.'; | |
cd0a25f4 | 455 | } |
862bbfbe KB |
456 | /* f format */ |
457 | else { | |
458 | for (; ++p < endp; *p2++ = *p); | |
459 | if (decpt) | |
460 | *p2++ = '.'; | |
cd0a25f4 | 461 | } |
862bbfbe KB |
462 | p = p2; |
463 | } | |
464 | /* | |
410bd0d3 KB |
465 | * if no fraction, the number was zero, and if no precision, can't |
466 | * show anything after the decimal point. | |
862bbfbe KB |
467 | */ |
468 | else if (!fract || !prec) { | |
469 | *startp++ = '0'; | |
410bd0d3 | 470 | if (decpt && !(format&GFORMAT)) |
862bbfbe | 471 | *startp++ = '.'; |
410bd0d3 | 472 | *startp = '\0'; |
ef9c9d35 | 473 | return(startp); |
862bbfbe KB |
474 | } |
475 | /* | |
476 | * if the format is g/G, and the resulting exponent will be less than | |
477 | * -4 use e/E format. If e/E format, compute exponent value. | |
478 | */ | |
479 | else if (format&GFORMAT && fract < .0001 || format&EFORMAT) { | |
480 | format |= EFORMAT; | |
481 | if (fract) | |
482 | for (p = startp; fract;) { | |
483 | fract = modf(fract * 10, &tmp); | |
484 | if (!tmp) { | |
485 | --expcnt; | |
486 | continue; | |
487 | } | |
488 | *p++ = (int)tmp + '0'; | |
489 | break; | |
490 | } | |
cd0a25f4 | 491 | else |
862bbfbe KB |
492 | *p++ = '0'; |
493 | ||
494 | /* g/G format, decrement precision for first digit */ | |
495 | if (format&GFORMAT && prec) | |
496 | --prec; | |
497 | ||
498 | /* add decimal after first non-zero digit */ | |
499 | if (decpt) | |
500 | *p++ = '.'; | |
cd0a25f4 | 501 | } |
862bbfbe KB |
502 | /* |
503 | * f format or g/G printed as f format; don't worry about decimal | |
504 | * point, if g/G format doesn't need it, will get stripped later. | |
505 | */ | |
cd0a25f4 | 506 | else { |
862bbfbe KB |
507 | p = startp; |
508 | *p++ = '0'; | |
509 | *p++ = '.'; | |
510 | } | |
511 | ||
aa876f9d KB |
512 | /* finish out requested precision */ |
513 | while (fract && prec-- > 0) { | |
514 | fract = modf(fract * 10, &tmp); | |
515 | *p++ = (int)tmp + '0'; | |
516 | } | |
517 | while (prec-- > 0) | |
518 | *p++ = '0'; | |
862bbfbe KB |
519 | |
520 | /* | |
521 | * if any fractional value left, "round" it back up to the beginning | |
522 | * of the number, fixing the exponent as necessary, and avoiding the | |
523 | * decimal point. | |
524 | */ | |
525 | if (fract) { | |
526 | (void)modf(fract * 10, &tmp); | |
527 | if (tmp > 4) { | |
528 | for (savep = p--;; *p-- = '0') { | |
529 | if (*p == '.') | |
530 | --p; | |
531 | if (p == startp) { | |
532 | *p = '1'; | |
533 | ++expcnt; | |
534 | break; | |
535 | } | |
536 | if (++*p <= '9') | |
537 | break; | |
538 | } | |
539 | p = savep; | |
cd0a25f4 | 540 | } |
862bbfbe KB |
541 | } |
542 | ||
543 | /* | |
544 | * if a g/G format and not alternate flag, lose trailing zeroes, | |
545 | * if e/E or g/G format, and last char is decimal point, lose it. | |
546 | */ | |
410bd0d3 | 547 | if (!(flags&ALT)) { |
862bbfbe KB |
548 | if (format&GFORMAT) |
549 | for (; p[-1] == '0'; --p); | |
550 | if (format&(GFORMAT|EFORMAT) && p[-1] == '.') | |
551 | --p; | |
552 | } | |
553 | ||
554 | /* if an e/E format, add exponent */ | |
555 | if (format&EFORMAT) { | |
556 | *p++ = fmtch; | |
557 | if (--expcnt < 0) { | |
558 | expcnt = -expcnt; | |
559 | *p++ = '-'; | |
cd0a25f4 | 560 | } |
862bbfbe KB |
561 | else |
562 | *p++ = '+'; | |
563 | *p++ = expcnt / 10 + '0'; | |
564 | *p++ = expcnt % 10 + '0'; | |
cd0a25f4 | 565 | } |
ef9c9d35 | 566 | return(p); |
cd0a25f4 | 567 | } |