summaryrefslogtreecommitdiff
path: root/libc/stdio/printf.c
diff options
context:
space:
mode:
authorManuel Novoa III <mjn3@codepoet.org>2001-02-27 21:33:59 +0000
committerManuel Novoa III <mjn3@codepoet.org>2001-02-27 21:33:59 +0000
commit82dd793fd07a21d4b03d3e0a1bd7434d302f35bb (patch)
treecc4df06c8e33aba7e0c221ef7bec66de123cd2cd /libc/stdio/printf.c
parent8cdb05af7df2bca002024f3553ea69e462d97c24 (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.c57
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)) {