Chameleon

Chameleon Svn Source Tree

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

Archive Download this file

Revision: 2182