Chameleon

Chameleon Svn Source Tree

Root/branches/cparm/i386/modules/Libstdio/vfprintf.c

1/*-
2 * Copyright (c) 1990, 1993
3 *The Regents of the University of California. All rights reserved.
4 *
5 * This code is derived from software contributed to Berkeley by
6 * Chris Torek.
7 *
8 * Redistribution and use in source and binary forms, with or without
9 * modification, are permitted provided that the following conditions
10 * are met:
11 * 1. Redistributions of source code must retain the above copyright
12 * notice, this list of conditions and the following disclaimer.
13 * 2. Redistributions in binary form must reproduce the above copyright
14 * notice, this list of conditions and the following disclaimer in the
15 * documentation and/or other materials provided with the distribution.
16 * 3. All advertising materials mentioning features or use of this software
17 * must display the following acknowledgement:
18 *This product includes software developed by the University of
19 *California, Berkeley and its contributors.
20 * 4. Neither the name of the University nor the names of its contributors
21 * may be used to endorse or promote products derived from this software
22 * without specific prior written permission.
23 *
24 * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
25 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
26 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
27 * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
28 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
29 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
30 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
31 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
32 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
33 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
34 * SUCH DAMAGE.
35 */
36
37#if defined(LIBC_SCCS) && !defined(lint)
38#if 0
39static char sccsid[] = "@(#)vfprintf.c8.1 (Berkeley) 6/4/93";
40#endif
41static const char rcsid[] =
42"$FreeBSD: src/lib/libc/stdio/vfprintf.c,v 1.22.2.6 2012/11/17 07:23:37 svnexp Exp $";
43#endif /* LIBC_SCCS and not lint */
44
45/*
46 * Actual printf innards.
47 *
48 * This code is large and complicated...
49 */
50
51#include <sys/types.h>
52
53#include <limits.h>
54#include "stdio.h"
55#include "libsaio.h"
56
57#if __STDC__
58#include <stdarg.h>
59#else
60#include <varargs.h>
61#endif
62
63//#include "libc_private.h"
64#include "local.h"
65#include "fvwrite.h"
66#include "printflocal.h"
67
68static int__sprint __P((FILE *, struct __suio *));
69static int__sbprintf __P((FILE *, const char *, va_list));
70static char *__ultoa __P((u_long, char *, int, int, char *));
71static char *__uqtoa __P((u_quad_t, char *, int, int, char *));
72
73/*
74 * Flush out all the vectors defined by the given uio,
75 * then reset it so that it can be reused.
76 */
77static int
78__sprint(FILE *fp, struct __suio *uio)
79{
80int err;
81
82if (uio->uio_resid == 0) {
83uio->uio_iovcnt = 0;
84return (0);
85}
86err = __sfvwrite(fp, uio);
87uio->uio_resid = 0;
88uio->uio_iovcnt = 0;
89return (err);
90}
91
92/*
93 * Helper function for `fprintf to unbuffered unix file': creates a
94 * temporary buffer. We only work on write-only files; this avoids
95 * worries about ungetc buffers and so forth.
96 */
97static int
98__sbprintf(FILE *fp, const char *fmt, va_list ap)
99{
100int ret;
101FILE fake;
102unsigned char buf[BUFSIZ];
103
104/* copy the important variables */
105fake._flags = fp->_flags & ~__SNBF;
106fake._file = fp->_file;
107fake._cookie = fp->_cookie;
108fake._write = fp->_write;
109
110/* set up the buffer */
111fake._bf._base = fake._p = buf;
112fake._bf._size = fake._w = sizeof(buf);
113fake._lbfsize = 0;/* not actually used, but Just In Case */
114
115/* do the work, then copy any error status */
116ret = vfprintf(&fake, fmt, ap);
117if (ret >= 0 && fflush(&fake))
118ret = EOF;
119if (fake._flags & __SERR)
120fp->_flags |= __SERR;
121return (ret);
122}
123
124/*
125 * Macros for converting digits to letters and vice versa
126 */
127#defineto_digit(c)((c) - '0')
128#define is_digit(c)((unsigned)to_digit(c) <= 9)
129#defineto_char(n)((n) + '0')
130
131/*
132 * Convert an unsigned long to ASCII for printf purposes, returning
133 * a pointer to the first character of the string representation.
134 * Octal numbers can be forced to have a leading zero; hex numbers
135 * use the given digits.
136 */
137static char *
138__ultoa(u_long val, char *endp, int base, int octzero, char *xdigs)
139{
140register char *cp = endp;
141register long sval;
142
143/*
144 * Handle the three cases separately, in the hope of getting
145 * better/faster code.
146 */
147switch (base) {
148 case 10:
149 if (val < 10) {/* many numbers are 1 digit */
150 *--cp = to_char(val);
151 return (cp);
152 }
153 /*
154 * On many machines, unsigned arithmetic is harder than
155 * signed arithmetic, so we do at most one unsigned mod and
156 * divide; this is sufficient to reduce the range of
157 * the incoming value to where signed arithmetic works.
158 */
159 if (val > LONG_MAX) {
160 *--cp = to_char(val % 10);
161 sval = val / 10;
162 } else
163 sval = val;
164 do {
165 *--cp = to_char(sval % 10);
166 sval /= 10;
167 } while (sval != 0);
168 break;
169
170 case 8:
171 do {
172 *--cp = to_char(val & 7);
173 val >>= 3;
174 } while (val);
175 if (octzero && *cp != '0')
176 *--cp = '0';
177 break;
178
179 case 16:
180 do {
181 *--cp = xdigs[val & 15];
182 val >>= 4;
183 } while (val);
184 break;
185
186 default:/* oops */
187 abort();
188}
189return (cp);
190}
191
192/* Identical to __ultoa, but for quads. */
193static char *
194__uqtoa(u_quad_t val, char *endp, int base, int octzero, char *xdigs)
195{
196char *cp = endp;
197quad_t sval;
198
199/* quick test for small values; __ultoa is typically much faster */
200/* (perhaps instead we should run until small, then call __ultoa?) */
201if (val <= ULONG_MAX)
202return (__ultoa((u_long)val, endp, base, octzero, xdigs));
203switch (base) {
204 case 10:
205 if (val < 10) {
206 *--cp = to_char(val % 10);
207 return (cp);
208 }
209 if (val > QUAD_MAX) {
210 *--cp = to_char(val % 10);
211 sval = val / 10;
212 } else
213 sval = val;
214 do {
215 *--cp = to_char(sval % 10);
216 sval /= 10;
217 } while (sval != 0);
218 break;
219
220 case 8:
221 do {
222 *--cp = to_char(val & 7);
223 val >>= 3;
224 } while (val);
225 if (octzero && *cp != '0')
226 *--cp = '0';
227 break;
228
229 case 16:
230 do {
231 *--cp = xdigs[val & 15];
232 val >>= 4;
233 } while (val);
234 break;
235
236 default:
237 abort();
238}
239return (cp);
240}
241
242#ifndef NO_FLOATING_POINT
243
244
245#else /* no FLOATING_POINT */
246
247#defineBUF68
248
249#endif /* FLOATING_POINT */
250
251#define STATIC_ARG_TBL_SIZE 8 /* Size of static argument table. */
252
253/*
254 * Flags used during conversion.
255 */
256#defineALT0x001/* alternate form */
257#defineHEXPREFIX0x002/* add 0x or 0X prefix */
258#defineLADJUST0x004/* left adjustment */
259#defineLONGDBL0x008/* long double */
260#defineLONGINT0x010/* long integer */
261#defineQUADINT0x020/* quad integer */
262#defineSHORTINT0x040/* short integer */
263#defineZEROPAD0x080/* zero (as opposed to blank) pad */
264#define FPT0x100/* Floating point number */
265int
266vfprintf(FILE *fp, const char *fmt0, va_list ap)
267{
268char *fmt;/* format string */
269int ch;/* character from fmt */
270int n, n2;/* handy integer (short term usage) */
271char *cp;/* handy char pointer (short term usage) */
272struct __siov *iovp;/* for PRINT macro */
273int flags;/* flags as above */
274int ret;/* return value accumulator */
275int width;/* width from format (%8d), or 0 */
276int prec;/* precision from format (%.3d), or -1 */
277char sign;/* sign prefix (' ', '+', '-', or \0) */
278#ifndef NO_FLOATING_POINT
279char *decimal_point = localeconv()->decimal_point;
280char softsign;/* temporary negative sign for floats */
281double _double;/* double precision arguments %[eEfgG] */
282int expt;/* integer value of exponent */
283int expsize;/* character count for expstr */
284int ndig;/* actual number of digits returned by cvt */
285char expstr[7];/* buffer for exponent string */
286char *dtoaresult;/* buffer allocated by dtoa */
287#endif
288u_longulval = 0;/* integer arguments %[diouxX] */
289u_quad_t uqval = 0;/* %q integers */
290int base;/* base for [diouxX] conversion */
291int dprec;/* a copy of prec if [diouxX], 0 otherwise */
292int realsz;/* field size expanded by dprec, sign, etc */
293int size;/* size of converted field or string */
294int prsize; /* max size of printed field */
295char *xdigs = NULL;/* digits for [xX] conversion */
296#define NIOV 8
297struct __suio uio;/* output information: summary */
298struct __siov iov[NIOV];/* ... and individual io vectors */
299char buf[BUF];/* space for %c, %[diouxX], %[eEfgG] */
300char ox[2];/* space for 0x hex-prefix */
301 union arg *argtable; /* args, built due to positional arg */
302union arg statargtable [STATIC_ARG_TBL_SIZE];
303 int nextarg; /* 1-based argument index */
304 va_list orgap; /* original argument pointer */
305
306/*
307 * Choose PADSIZE to trade efficiency vs. size. If larger printf
308 * fields occur frequently, increase PADSIZE and make the initialisers
309 * below longer.
310 */
311#definePADSIZE16/* pad chunk size */
312static char blanks[PADSIZE] =
313 {' ',' ',' ',' ',' ',' ',' ',' ',' ',' ',' ',' ',' ',' ',' ',' '};
314static char zeroes[PADSIZE] =
315 {'0','0','0','0','0','0','0','0','0','0','0','0','0','0','0','0'};
316
317/*
318 * BEWARE, these `goto error' on error, and PAD uses `n'.
319 */
320#definePRINT(ptr, len) { \
321iovp->iov_base = (ptr); \
322iovp->iov_len = (len); \
323uio.uio_resid += (len); \
324iovp++; \
325if (++uio.uio_iovcnt >= NIOV) { \
326if (__sprint(fp, &uio)) \
327goto error; \
328iovp = iov; \
329} \
330}
331#definePAD(howmany, with) { \
332if ((n = (howmany)) > 0) { \
333while (n > PADSIZE) { \
334PRINT(with, PADSIZE); \
335n -= PADSIZE; \
336} \
337PRINT(with, n); \
338} \
339}
340#defineFLUSH() { \
341if (uio.uio_resid && __sprint(fp, &uio)) \
342goto error; \
343uio.uio_iovcnt = 0; \
344iovp = iov; \
345}
346
347/*
348 * Get the argument indexed by nextarg. If the argument table is
349 * built, use it to get the argument. If its not, get the next
350 * argument (and arguments must be gotten sequentially).
351 */
352#define GETARG(type) \
353((argtable != NULL) ? *((type*)(&argtable[nextarg++])) : \
354(nextarg++, va_arg(ap, type)))
355
356/*
357 * To extend shorts properly, we need both signed and unsigned
358 * argument extraction methods.
359 */
360#defineSARG() \
361(flags&LONGINT ? GETARG(long) : \
362flags&SHORTINT ? (long)(short)GETARG(int) : \
363flags&CHARINT ? (long)(signed char)GETARG(int) : \
364(long)GETARG(int))
365#defineUARG() \
366(flags&LONGINT ? GETARG(u_long) : \
367flags&SHORTINT ? (u_long)(u_short)GETARG(int) : \
368flags&CHARINT ? (u_long)(u_char)GETARG(int) : \
369(u_long)GETARG(u_int))
370#defineINTMAX_SIZE(INTMAXT|SIZET|PTRDIFFT|LLONGINT)
371#define SJARG() \
372(flags&INTMAXT ? GETARG(intmax_t) : \
373flags&SIZET ? (intmax_t)GETARG(ssize_t) : \
374flags&PTRDIFFT ? (intmax_t)GETARG(ptrdiff_t) : \
375(intmax_t)GETARG(long long))
376#defineUJARG() \
377(flags&INTMAXT ? GETARG(uintmax_t) : \
378flags&SIZET ? (uintmax_t)GETARG(size_t) : \
379flags&PTRDIFFT ? (uintmax_t)GETARG(ptrdiff_t) : \
380(uintmax_t)GETARG(unsigned long long))
381
382/*
383 * Get * arguments, including the form *nn$. Preserve the nextarg
384 * that the argument can be gotten once the type is determined.
385 */
386#define GETASTER(val) \
387n2 = 0; \
388cp = fmt; \
389while (is_digit(*cp)) { \
390n2 = 10 * n2 + to_digit(*cp); \
391cp++; \
392} \
393if (*cp == '$') { \
394int hold = nextarg; \
395if (argtable == NULL) { \
396argtable = statargtable; \
397if (__find_arguments (fmt0, orgap, &argtable)) { \
398ret = EOF; \
399goto error; \
400} \
401} \
402nextarg = n2; \
403val = GETARG (int); \
404nextarg = hold; \
405fmt = ++cp; \
406} else { \
407val = GETARG (int); \
408}
409
410
411#ifndef NO_FLOATING_POINT
412dtoaresult = NULL;
413#endif
414/* sorry, fprintf(read_only_file, "") returns EOF, not 0 */
415if (prepwrite(fp) != 0)
416return (EOF);
417
418/* optimise fprintf(stderr) (and other unbuffered Unix files) */
419if ((fp->_flags & (__SNBF|__SWR|__SRW)) == (__SNBF|__SWR) &&
420 fp->_file >= 0) {
421return (__sbprintf(fp, fmt0, ap));
422}
423
424fmt = (char *)fmt0;
425 argtable = NULL;
426 nextarg = 1;
427 orgap = ap;
428uio.uio_iov = iovp = iov;
429uio.uio_resid = 0;
430uio.uio_iovcnt = 0;
431ret = 0;
432
433/*
434 * Scan the format for conversions (`%' character).
435 */
436for (;;) {
437for (cp = fmt; (ch = *fmt) != '\0' && ch != '%'; fmt++)
438 /* void */;
439if ((n = fmt - cp) != 0) {
440if ((unsigned)ret + n > INT_MAX) {
441ret = EOF;
442goto error;
443}
444PRINT(cp, n);
445ret += n;
446}
447if (ch == '\0')
448goto done;
449fmt++;/* skip over '%' */
450
451flags = 0;
452dprec = 0;
453width = 0;
454prec = -1;
455sign = '\0';
456
457 rflag:ch = *fmt++;
458 reswitch:switch (ch) {
459case ' ':
460/*
461 * ``If the space and + flags both appear, the space
462 * flag will be ignored.''
463 *-- ANSI X3J11
464 */
465if (!sign)
466sign = ' ';
467goto rflag;
468case '#':
469flags |= ALT;
470goto rflag;
471case '*':
472/*
473 * ``A negative field width argument is taken as a
474 * - flag followed by a positive field width.''
475 *-- ANSI X3J11
476 * They don't exclude field widths read from args.
477 */
478GETASTER (width);
479if (width >= 0)
480goto rflag;
481width = -width;
482/* FALLTHROUGH */
483case '-':
484flags |= LADJUST;
485goto rflag;
486case '+':
487sign = '+';
488goto rflag;
489case '.':
490if ((ch = *fmt++) == '*') {
491GETASTER (n);
492prec = n < 0 ? -1 : n;
493goto rflag;
494}
495n = 0;
496while (is_digit(ch)) {
497n = 10 * n + to_digit(ch);
498ch = *fmt++;
499}
500prec = n < 0 ? -1 : n;
501goto reswitch;
502case '0':
503/*
504 * ``Note that 0 is taken as a flag, not as the
505 * beginning of a field width.''
506 *-- ANSI X3J11
507 */
508flags |= ZEROPAD;
509goto rflag;
510case '1': case '2': case '3': case '4':
511case '5': case '6': case '7': case '8': case '9':
512n = 0;
513do {
514n = 10 * n + to_digit(ch);
515ch = *fmt++;
516} while (is_digit(ch));
517if (ch == '$') {
518nextarg = n;
519 if (argtable == NULL) {
520 argtable = statargtable;
521 __find_arguments (fmt0, orgap,
522 &argtable);
523}
524goto rflag;
525 }
526width = n;
527goto reswitch;
528#ifndef NO_FLOATING_POINT
529case 'L':
530flags |= LONGDBL;
531goto rflag;
532#endif
533case 'h':
534flags |= SHORTINT;
535goto rflag;
536case 'l':
537if (flags & LONGINT)
538flags |= QUADINT;
539else
540flags |= LONGINT;
541goto rflag;
542case 'q':
543flags |= QUADINT;
544goto rflag;
545case 'c':
546*(cp = buf) = GETARG(int);
547size = 1;
548sign = '\0';
549break;
550case 'D':
551flags |= LONGINT;
552/*FALLTHROUGH*/
553case 'd':
554case 'i':
555if (flags & QUADINT) {
556uqval = GETARG(quad_t);
557if ((quad_t)uqval < 0) {
558uqval = -uqval;
559sign = '-';
560}
561} else {
562ulval = SARG();
563if ((long)ulval < 0) {
564ulval = -ulval;
565sign = '-';
566}
567}
568base = 10;
569goto number;
570#ifndef NO_FLOATING_POINT
571case 'e':
572case 'E':
573case 'f':
574goto fp_begin;
575case 'g':
576case 'G':
577if (prec == 0)
578prec = 1;
579 fp_begin:if (prec == -1)
580 prec = DEFPREC;
581if (flags & LONGDBL)
582 /* XXX this loses precision. */
583_double = (double)GETARG(long double);
584else
585_double = GETARG(double);
586/* do this before tricky precision changes */
587if (isinf(_double)) {
588if (_double < 0)
589sign = '-';
590cp = "Inf";
591size = 3;
592break;
593}
594if (isnan(_double)) {
595cp = "NaN";
596size = 3;
597break;
598}
599flags |= FPT;
600if (dtoaresult != NULL) {
601free(dtoaresult);
602dtoaresult = NULL;
603}
604cp = cvt(_double, prec, flags, &softsign,
605 &expt, ch, &ndig, &dtoaresult);
606if (ch == 'g' || ch == 'G') {
607if (expt <= -4 || expt > prec)
608ch = (ch == 'g') ? 'e' : 'E';
609else
610ch = 'g';
611}
612if (ch <= 'e') {/* 'e' or 'E' fmt */
613--expt;
614expsize = exponent(expstr, expt, ch);
615size = expsize + ndig;
616if (ndig > 1 || flags & ALT)
617++size;
618} else if (ch == 'f') {/* f fmt */
619if (expt > 0) {
620size = expt;
621if (prec || flags & ALT)
622size += prec + 1;
623} else/* "0.X" */
624size = prec + 2;
625} else if (expt >= ndig) {/* fixed g fmt */
626size = expt;
627if (flags & ALT)
628++size;
629} else
630size = ndig + (expt > 0 ?
631 1 : 2 - expt);
632
633if (softsign)
634sign = '-';
635break;
636#endif /* FLOATING_POINT */
637case 'n':
638if (flags & QUADINT)
639*GETARG(quad_t *) = ret;
640else if (flags & LONGINT)
641*GETARG(long *) = ret;
642else if (flags & SHORTINT)
643*GETARG(short *) = ret;
644else
645*GETARG(int *) = ret;
646continue;/* no output */
647case 'O':
648flags |= LONGINT;
649/*FALLTHROUGH*/
650case 'o':
651if (flags & QUADINT)
652uqval = GETARG(u_quad_t);
653else
654ulval = UARG();
655base = 8;
656goto nosign;
657case 'p':
658/*
659 * ``The argument shall be a pointer to void. The
660 * value of the pointer is converted to a sequence
661 * of printable characters, in an implementation-
662 * defined manner.''
663 *-- ANSI X3J11
664 */
665ulval = (u_long)GETARG(void *);
666base = 16;
667xdigs = "0123456789abcdef";
668flags = (flags & ~QUADINT) | HEXPREFIX;
669ch = 'x';
670goto nosign;
671case 's':
672if ((cp = GETARG(char *)) == NULL)
673cp = "(null)";
674if (prec >= 0) {
675/*
676 * can't use strlen; can only look for the
677 * NUL in the first `prec' characters, and
678 * strlen() will go further.
679 */
680char *p = memchr(cp, 0, (size_t)prec);
681
682if (p != NULL) {
683size = p - cp;
684if (size > prec)
685size = prec;
686} else
687size = prec;
688} else
689size = strlen(cp);
690sign = '\0';
691break;
692case 'U':
693flags |= LONGINT;
694/*FALLTHROUGH*/
695case 'u':
696if (flags & QUADINT)
697uqval = GETARG(u_quad_t);
698else
699ulval = UARG();
700base = 10;
701goto nosign;
702case 'X':
703xdigs = "0123456789ABCDEF";
704goto hex;
705case 'x':
706xdigs = "0123456789abcdef";
707 hex:if (flags & QUADINT)
708 uqval = GETARG(u_quad_t);
709 else
710 ulval = UARG();
711base = 16;
712/* leading 0x/X only if non-zero */
713if (flags & ALT &&
714 (flags & QUADINT ? uqval != 0 : ulval != 0))
715flags |= HEXPREFIX;
716
717/* unsigned conversions */
718 nosign:sign = '\0';
719/*
720 * ``... diouXx conversions ... if a precision is
721 * specified, the 0 flag will be ignored.''
722 *-- ANSI X3J11
723 */
724 number:if ((dprec = prec) >= 0)
725 flags &= ~ZEROPAD;
726
727/*
728 * ``The result of converting a zero value with an
729 * explicit precision of zero is no characters.''
730 *-- ANSI X3J11
731 */
732cp = buf + BUF;
733if (flags & QUADINT) {
734if (uqval != 0 || prec != 0)
735cp = __uqtoa(uqval, cp, base,
736 flags & ALT, xdigs);
737} else {
738if (ulval != 0 || prec != 0)
739cp = __ultoa(ulval, cp, base,
740 flags & ALT, xdigs);
741}
742size = buf + BUF - cp;
743break;
744default:/* "%?" prints ?, unless ? is NUL */
745if (ch == '\0')
746goto done;
747/* pretend it was %c with argument ch */
748cp = buf;
749*cp = ch;
750size = 1;
751sign = '\0';
752break;
753 }
754
755/*
756 * All reasonable formats wind up here. At this point, `cp'
757 * points to a string which (if not flags&LADJUST) should be
758 * padded out to `width' places. If flags&ZEROPAD, it should
759 * first be prefixed by any sign or other prefix; otherwise,
760 * it should be blank padded before the prefix is emitted.
761 * After any left-hand padding and prefixing, emit zeroes
762 * required by a decimal [diouxX] precision, then print the
763 * string proper, then emit zeroes required by any leftover
764 * floating precision; finally, if LADJUST, pad with blanks.
765 *
766 * Compute actual size, so we know how much to pad.
767 * size excludes decimal prec; realsz includes it.
768 */
769realsz = dprec > size ? dprec : size;
770if (sign)
771realsz++;
772else if (flags & HEXPREFIX)
773realsz += 2;
774
775prsize = width > realsz ? width : realsz;
776if ((unsigned)ret + prsize > INT_MAX) {
777ret = EOF;
778goto error;
779}
780
781/* right-adjusting blank padding */
782if ((flags & (LADJUST|ZEROPAD)) == 0)
783PAD(width - realsz, blanks);
784
785/* prefix */
786if (sign) {
787PRINT(&sign, 1);
788} else if (flags & HEXPREFIX) {
789ox[0] = '0';
790ox[1] = ch;
791PRINT(ox, 2);
792}
793
794/* right-adjusting zero padding */
795if ((flags & (LADJUST|ZEROPAD)) == ZEROPAD)
796PAD(width - realsz, zeroes);
797
798/* leading zeroes from decimal precision */
799PAD(dprec - size, zeroes);
800
801/* the string or number proper */
802#ifndef NO_FLOATING_POINT
803if ((flags & FPT) == 0) {
804PRINT(cp, size);
805} else {/* glue together f_p fragments */
806if (ch >= 'f') {/* 'f' or 'g' */
807if (_double == 0) {
808/* kludge for __dtoa irregularity */
809PRINT("0", 1);
810if (expt < ndig || (flags & ALT) != 0) {
811PRINT(decimal_point, 1);
812PAD(ndig - 1, zeroes);
813}
814} else if (expt <= 0) {
815PRINT("0", 1);
816PRINT(decimal_point, 1);
817PAD(-expt, zeroes);
818PRINT(cp, ndig);
819} else if (expt >= ndig) {
820PRINT(cp, ndig);
821PAD(expt - ndig, zeroes);
822if (flags & ALT)
823PRINT(decimal_point, 1);
824} else {
825PRINT(cp, expt);
826cp += expt;
827PRINT(decimal_point, 1);
828PRINT(cp, ndig-expt);
829}
830} else {/* 'e' or 'E' */
831if (ndig > 1 || flags & ALT) {
832ox[0] = *cp++;
833ox[1] = *decimal_point;
834PRINT(ox, 2);
835if (_double) {
836PRINT(cp, ndig-1);
837} else/* 0.[0..] */
838 /* __dtoa irregularity */
839PAD(ndig - 1, zeroes);
840} else/* XeYYY */
841PRINT(cp, 1);
842PRINT(expstr, expsize);
843}
844}
845#else
846PRINT(cp, size);
847#endif
848/* left-adjusting padding (always blank) */
849if (flags & LADJUST)
850PAD(width - realsz, blanks);
851
852/* finally, adjust ret */
853ret += prsize;
854
855FLUSH();/* copy out the I/O vectors */
856}
857done:
858FLUSH();
859error:
860#ifndef NO_FLOATING_POINT
861if (dtoaresult != NULL)
862free(dtoaresult);
863#endif
864if (__sferror(fp))
865ret = EOF;
866 if ((argtable != NULL) && (argtable != statargtable))
867 free (argtable);
868return (ret);
869/* NOTREACHED */
870}
871

Archive Download this file

Revision: 2154