diff options
author | Manuel Novoa III <mjn3@codepoet.org> | 2001-02-27 21:33:59 +0000 |
---|---|---|
committer | Manuel Novoa III <mjn3@codepoet.org> | 2001-02-27 21:33:59 +0000 |
commit | 82dd793fd07a21d4b03d3e0a1bd7434d302f35bb (patch) | |
tree | cc4df06c8e33aba7e0c221ef7bec66de123cd2cd /libc/stdio/printf.c | |
parent | 8cdb05af7df2bca002024f3553ea69e462d97c24 (diff) |
stdio mostly rewritten... passes lots of tests now.
printf now supports long double, plus some bug fixes.
Diffstat (limited to 'libc/stdio/printf.c')
-rw-r--r-- | libc/stdio/printf.c | 57 |
1 files changed, 28 insertions, 29 deletions
diff --git a/libc/stdio/printf.c b/libc/stdio/printf.c index f6ca8dda4..06cf6a5b2 100644 --- a/libc/stdio/printf.c +++ b/libc/stdio/printf.c @@ -267,7 +267,7 @@ int vsnprintf(char *sp, size_t size, __const char *fmt, va_list ap) */ f.bufwrite = (char *) ((unsigned) -1); f.bufpos = sp; - f.mode = _IOFBF | __MODE_WRITE; + f.mode = _IOFBF; rv = vfnprintf(&f, size, fmt, ap); if (size) { /* If this is going to a buffer, */ @@ -283,25 +283,17 @@ int vsnprintf(char *sp, size_t size, __const char *fmt, va_list ap) */ extern int vdprintf(int fd, const char *fmt, va_list ap) { -#if 0 - FILE f = {f.unbuf, f.unbuf, f.unbuf, f.unbuf, f.unbuf + sizeof(f.unbuf), - fd, _IONBF | __MODE_WRITE}; - - assert(fd >= 0); /* fd==0 may no longer be stdin */ - - return vfnprintf(&f, -1, fmt, ap); -#else char buf[BUFSIZ]; - FILE f = {buf, buf, buf, buf, buf + sizeof(buf), - fd, _IOFBF | __MODE_WRITE}; + FILE f = {buf, 0, buf+sizeof(buf), buf, buf+sizeof(buf), 0, fd, _IOFBF}; int rv; - assert(fd >= 0); /* fd==0 may no longer be stdin */ - rv = vfnprintf(&f, -1, fmt, ap); - fflush(&f); + + if (fflush(&f)) { + return -1; + } + return rv; -#endif } #endif @@ -311,7 +303,7 @@ extern char *__ultostr(char *buf, unsigned long uval, int base, int uppercase); extern char *__ltostr(char *buf, long val, int base, int uppercase); extern char *__ulltostr(char *buf, unsigned long long uval, int base, int uppercase); extern char *__lltostr(char *buf, long long val, int base, int uppercase); -extern int __dtostr(FILE * fp, size_t size, double x, +extern int __dtostr(FILE * fp, size_t size, long double x, char flag[], int width, int preci, char mode); enum { @@ -353,7 +345,7 @@ static const char u_radix[] = "\x02\x08\x10\x10\x10\x0a"; int vfnprintf(FILE * op, size_t max_size, const char *fmt, va_list ap) { - int i, cnt = 0, lval; + int i, cnt, lval; char *p; const char *fmt0; int buffer_mode; @@ -367,7 +359,9 @@ int vfnprintf(FILE * op, size_t max_size, const char *fmt, va_list ap) #endif char flag[sizeof(spec)]; - /* This speeds things up a bit for unbuffered */ + cnt = 0; + + /* This speeds things up a bit for line unbuffered */ buffer_mode = (op->mode & __MODE_BUF); op->mode &= (~__MODE_BUF); @@ -375,9 +369,6 @@ int vfnprintf(FILE * op, size_t max_size, const char *fmt, va_list ap) if (*fmt == '%') { fmt0 = fmt; /* save our position in case of bad format */ ++fmt; - if (buffer_mode == _IONBF) { - fflush(op); - } width = -1; /* min field width */ preci = -5; /* max string width or mininum digits */ radix = 10; /* number base */ @@ -511,7 +502,7 @@ int vfnprintf(FILE * op, size_t max_size, const char *fmt, va_list ap) if (flag[FLAG_HASH] && (*p != '0')) { /* non-zero */ if (radix == 8) { *--p = '0'; /* add leadding zero */ - } else { /* either 2 or 16 */ + } else if (radix != 10) { /* either 2 or 16 */ flag[FLAG_PLUS] = '0'; *--p = 'b'; if (radix == 16) { @@ -556,6 +547,9 @@ int vfnprintf(FILE * op, size_t max_size, const char *fmt, va_list ap) *p = va_arg(ap, int); } else { /* string */ p = va_arg(ap, char *); + if (!p) { + p = "(null)"; + } } #if WANT_DOUBLE || WANT_DOUBLE_ERROR } else if (p-u_spec < 27) { /* floating point */ @@ -564,11 +558,15 @@ int vfnprintf(FILE * op, size_t max_size, const char *fmt, va_list ap) if (preci < 0) { preci = 6; } - cnt += __dtostr(op, max_size, va_arg(ap, double), + cnt += __dtostr(op, max_size, + (long double) ((lval > 1) + ? va_arg(ap, long double) + : va_arg(ap, double)), flag, width, preci, *fmt); goto nextfmt; #elif WANT_DOUBLE_ERROR - (void) va_arg(ap,double); /* carry on */ + (void) ((lval > 1) ? va_arg(ap, long double) + : va_arg(ap, double)); /* carry on */ p = (char *) dbl_err; #endif /* WANT_DOUBLE */ } @@ -604,7 +602,11 @@ int vfnprintf(FILE * op, size_t max_size, const char *fmt, va_list ap) || (*fmt == 'm') #endif ) { - len = preci; + if (len > preci) { + len = preci; + } else { + preci = len; + } } preci -= len; if (preci < 0) { @@ -678,11 +680,8 @@ int vfnprintf(FILE * op, size_t max_size, const char *fmt, va_list ap) } op->mode |= buffer_mode; - if (buffer_mode == _IONBF) { - fflush(op); - } if (buffer_mode == _IOLBF) { - op->bufwrite = op->bufstart; + op->bufwrite = op->bufpos; } if (ferror(op)) { |