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