summaryrefslogtreecommitdiff
path: root/libc
diff options
context:
space:
mode:
authorManuel Novoa III <mjn3@codepoet.org>2005-07-30 01:21:47 +0000
committerManuel Novoa III <mjn3@codepoet.org>2005-07-30 01:21:47 +0000
commitb0a7157456eb4a4efde25e3efbc1beb878612c78 (patch)
treed1500326f7b77bfd2bf06ae44e6a239e56bca4aa /libc
parent7e3139b5a9852bff433210b6bbfb2ae62f64353b (diff)
Sigh... I wasn't checking for output errors. NIST/PCTS caught it.
Hack in some temporary fixes until I have time to clean it up a bit more. Also rework _fpmaxtostr to reduce the size a bit and (hopefully) allow it to build for m68k (vapier tested an earlier version a while back).
Diffstat (limited to 'libc')
-rw-r--r--libc/stdio/_fpmaxtostr.c388
-rw-r--r--libc/stdio/vfprintf.c108
2 files changed, 279 insertions, 217 deletions
diff --git a/libc/stdio/_fpmaxtostr.c b/libc/stdio/_fpmaxtostr.c
index 7fd67ffb4..b9aacdca8 100644
--- a/libc/stdio/_fpmaxtostr.c
+++ b/libc/stdio/_fpmaxtostr.c
@@ -11,8 +11,8 @@
#include <locale.h>
#include <bits/uClibc_fpmax.h>
-typedef void (__fp_outfunc_t)(FILE *fp, intptr_t type, intptr_t len,
- intptr_t buf);
+typedef size_t (__fp_outfunc_t)(FILE *fp, intptr_t type, intptr_t len,
+ intptr_t buf);
/* Copyright (C) 2000, 2001, 2003 Manuel Novoa III
@@ -198,14 +198,13 @@ static const __fpmax_t exp16_table[] = {
#define FPO_STR_WIDTH (0x80 | ' ');
#define FPO_STR_PREC 'p'
-size_t _fpmaxtostr(FILE * fp, __fpmax_t x, struct printf_info *info,
- __fp_outfunc_t fp_outfunc)
+ssize_t _fpmaxtostr(FILE * fp, __fpmax_t x, struct printf_info *info,
+ __fp_outfunc_t fp_outfunc)
{
#ifdef __UCLIBC_HAS_HEXADECIMAL_FLOATS__
__fpmax_t lower_bnd;
__fpmax_t upper_bnd = 1e9;
#endif /* __UCLIBC_HAS_HEXADECIMAL_FLOATS__ */
- uint_fast32_t digit_block;
#ifdef __UCLIBC_HAS_HEXADECIMAL_FLOATS__
uint_fast32_t base = 10;
const __fpmax_t *power_table;
@@ -221,9 +220,8 @@ size_t _fpmaxtostr(FILE * fp, __fpmax_t x, struct printf_info *info,
int nblk2; /* This does not need to be initialized. */
const char *ts; /* This does not need to be initialized. */
#endif /* __UCLIBC_HAS_GLIBC_DIGIT_GROUPING__ */
- int i, j;
int round, o_exp;
- int exp, exp_neg;
+ int exp;
int width, preci;
int cnt;
char *s;
@@ -304,34 +302,36 @@ size_t _fpmaxtostr(FILE * fp, __fpmax_t x, struct printf_info *info,
goto EXIT_SPECIAL;
}
+ {
+ int i, j;
#ifdef __UCLIBC_MJN3_ONLY__
#warning TODO: Clean up defines when hexadecimal float notation is unsupported.
#endif /* __UCLIBC_MJN3_ONLY__ */
#ifdef __UCLIBC_HAS_HEXADECIMAL_FLOATS__
- if ((mode|0x20) == 'a') {
- lower_bnd = 0x1.0p31L;
- upper_bnd = 0x1.0p32L;
- power_table = exp16_table;
- exp = HEX_DIGITS_PER_BLOCK - 1;
- i = EXP16_TABLE_SIZE;
- j = EXP16_TABLE_MAX;
- dpb = HEX_DIGITS_PER_BLOCK;
- ndb = NUM_HEX_DIGIT_BLOCKS;
- nd = NUM_HEX_DIGITS;
- base = 16;
- } else {
- lower_bnd = 1e8;
-/* upper_bnd = 1e9; */
- power_table = exp10_table;
- exp = DIGITS_PER_BLOCK - 1;
- i = EXP10_TABLE_SIZE;
- j = EXP10_TABLE_MAX;
-/* dpb = DIGITS_PER_BLOCK; */
-/* ndb = NUM_DIGIT_BLOCKS; */
-/* base = 10; */
- }
+ if ((mode|0x20) == 'a') {
+ lower_bnd = 0x1.0p31L;
+ upper_bnd = 0x1.0p32L;
+ power_table = exp16_table;
+ exp = HEX_DIGITS_PER_BLOCK - 1;
+ i = EXP16_TABLE_SIZE;
+ j = EXP16_TABLE_MAX;
+ dpb = HEX_DIGITS_PER_BLOCK;
+ ndb = NUM_HEX_DIGIT_BLOCKS;
+ nd = NUM_HEX_DIGITS;
+ base = 16;
+ } else {
+ lower_bnd = 1e8;
+ /* upper_bnd = 1e9; */
+ power_table = exp10_table;
+ exp = DIGITS_PER_BLOCK - 1;
+ i = EXP10_TABLE_SIZE;
+ j = EXP10_TABLE_MAX;
+ /* dpb = DIGITS_PER_BLOCK; */
+ /* ndb = NUM_DIGIT_BLOCKS; */
+ /* base = 10; */
+ }
@@ -345,32 +345,35 @@ size_t _fpmaxtostr(FILE * fp, __fpmax_t x, struct printf_info *info,
#define ndb NUM_DIGIT_BLOCKS
#define nd DECIMAL_DIG
- exp = DIGITS_PER_BLOCK - 1;
- i = EXP10_TABLE_SIZE;
- j = EXP10_TABLE_MAX;
+ exp = DIGITS_PER_BLOCK - 1;
+ i = EXP10_TABLE_SIZE;
+ j = EXP10_TABLE_MAX;
#endif /* __UCLIBC_HAS_HEXADECIMAL_FLOATS__ */
- exp_neg = 0;
- if (x < lower_bnd) { /* Do we need to scale up or down? */
- exp_neg = 1;
- }
-
- do {
- --i;
- if (exp_neg) {
- if (x * power_table[i] < upper_bnd) {
- x *= power_table[i];
- exp -= j;
- }
- } else {
- if (x / power_table[i] >= lower_bnd) {
- x /= power_table[i];
- exp += j;
+ {
+ int exp_neg = 0;
+ if (x < lower_bnd) { /* Do we need to scale up or down? */
+ exp_neg = 1;
}
+
+ do {
+ --i;
+ if (exp_neg) {
+ if (x * power_table[i] < upper_bnd) {
+ x *= power_table[i];
+ exp -= j;
+ }
+ } else {
+ if (x / power_table[i] >= lower_bnd) {
+ x /= power_table[i];
+ exp += j;
+ }
+ }
+ j >>= 1;
+ } while (i);
}
- j >>= 1;
- } while (i);
+ }
if (x >= upper_bnd) { /* Handle bad rounding case. */
x /= power_table[0];
++exp;
@@ -378,22 +381,25 @@ size_t _fpmaxtostr(FILE * fp, __fpmax_t x, struct printf_info *info,
assert(x < upper_bnd);
GENERATE_DIGITS:
- s = buf + 2; /* Leave space for '\0' and '0'. */
- i = 0;
- do {
- digit_block = (uint_fast32_t) x;
- assert(digit_block < upper_bnd);
+ {
+ int i, j;
+ s = buf + 2; /* Leave space for '\0' and '0'. */
+ i = 0;
+ do {
+ uint_fast32_t digit_block = (uint_fast32_t) x;
+ assert(digit_block < upper_bnd);
#ifdef __UCLIBC_MJN3_ONLY__
#warning CONSIDER: Can rounding be a problem?
#endif /* __UCLIBC_MJN3_ONLY__ */
- x = (x - digit_block) * upper_bnd;
- s += dpb;
- j = 0;
- do {
- s[- ++j] = '0' + (digit_block % base);
- digit_block /= base;
- } while (j < dpb);
- } while (++i < ndb);
+ x = (x - digit_block) * upper_bnd;
+ s += dpb;
+ j = 0;
+ do {
+ s[- ++j] = '0' + (digit_block % base);
+ digit_block /= base;
+ } while (j < dpb);
+ } while (++i < ndb);
+ }
/*************************************************************************/
@@ -421,18 +427,21 @@ size_t _fpmaxtostr(FILE * fp, __fpmax_t x, struct printf_info *info,
*s++ = 0; /* Terminator for rounding and 0-triming. */
*s = '0'; /* Space to round. */
- i = 0;
- e = s + nd + 1;
- if (round < nd) {
- e = s + round + 2;
- if (*e >= '0' + (base/2)) { /* NOTE: We always round away from 0! */
- i = 1;
+ {
+ int i;
+ i = 0;
+ e = s + nd + 1;
+ if (round < nd) {
+ e = s + round + 2;
+ if (*e >= '0' + (base/2)) { /* NOTE: We always round away from 0! */
+ i = 1;
+ }
}
- }
- do { /* Handle rounding and trim trailing 0s. */
- *--e += i; /* Add the carry. */
- } while ((*e == '0') || (*e > '0' - 1 + base));
+ do { /* Handle rounding and trim trailing 0s. */
+ *--e += i; /* Add the carry. */
+ } while ((*e == '0') || (*e > '0' - 1 + base));
+ }
#ifdef __UCLIBC_HAS_HEXADECIMAL_FLOATS__
if ((mode|0x20) == 'a') {
@@ -480,80 +489,81 @@ size_t _fpmaxtostr(FILE * fp, __fpmax_t x, struct printf_info *info,
sign_str[5] = 0;
ppc = pc_fwi + 6;
- i = e - s; /* Total digits is 'i'. */
- if (o_exp >= 0) {
+ {
+ int i = e - s; /* Total digits is 'i'. */
+ if (o_exp >= 0) {
#ifdef __UCLIBC_HAS_GLIBC_DIGIT_GROUPING__
- const char *p;
+ const char *p;
- if (PRINT_INFO_FLAG_VAL(info,group)
- && *(p = __UCLIBC_CURLOCALE_DATA.grouping)
- ) {
- int nblk1;
+ if (PRINT_INFO_FLAG_VAL(info,group)
+ && *(p = __UCLIBC_CURLOCALE_DATA.grouping)
+ ) {
+ int nblk1;
- nblk2 = nblk1 = *p;
- if (*++p) {
- nblk2 = *p;
- assert(!*++p);
- }
+ nblk2 = nblk1 = *p;
+ if (*++p) {
+ nblk2 = *p;
+ assert(!*++p);
+ }
- if (o_exp >= nblk1) {
- num_groups = (o_exp - nblk1) / nblk2 + 1;
- initial_group = (o_exp - nblk1) % nblk2;
+ if (o_exp >= nblk1) {
+ num_groups = (o_exp - nblk1) / nblk2 + 1;
+ initial_group = (o_exp - nblk1) % nblk2;
#ifdef __UCLIBC_HAS_WCHAR__
- if (PRINT_INFO_FLAG_VAL(info,wide)) {
- /* _fp_out_wide() will fix this up. */
- ts = fmt + THOUSEP_OFFSET;
- tslen = 1;
- } else {
+ if (PRINT_INFO_FLAG_VAL(info,wide)) {
+ /* _fp_out_wide() will fix this up. */
+ ts = fmt + THOUSEP_OFFSET;
+ tslen = 1;
+ } else {
#endif /* __UCLIBC_HAS_WCHAR__ */
- ts = __UCLIBC_CURLOCALE_DATA.thousands_sep;
- tslen = __UCLIBC_CURLOCALE_DATA.thousands_sep_len;
+ ts = __UCLIBC_CURLOCALE_DATA.thousands_sep;
+ tslen = __UCLIBC_CURLOCALE_DATA.thousands_sep_len;
#ifdef __UCLIBC_HAS_WCHAR__
- }
+ }
#endif /* __UCLIBC_HAS_WCHAR__ */
- width -= num_groups * tslen;
+ width -= num_groups * tslen;
+ }
}
- }
#endif /* __UCLIBC_HAS_GLIBC_DIGIT_GROUPING__ */
- ppc[0] = FPO_STR_PREC;
- ppc[2] = (intptr_t)(s);
- if (o_exp >= i) { /* all digit(s) left of decimal */
- ppc[1] = i;
- ppc += 3;
- o_exp -= i;
- i = 0;
- if (o_exp>0) { /* have 0s left of decimal */
- ppc[0] = FPO_ZERO_PAD;
+ ppc[0] = FPO_STR_PREC;
+ ppc[2] = (intptr_t)(s);
+ if (o_exp >= i) { /* all digit(s) left of decimal */
+ ppc[1] = i;
+ ppc += 3;
+ o_exp -= i;
+ i = 0;
+ if (o_exp>0) { /* have 0s left of decimal */
+ ppc[0] = FPO_ZERO_PAD;
+ ppc[1] = o_exp;
+ ppc[2] = (intptr_t)(fmt + EMPTY_STRING_OFFSET);
+ ppc += 3;
+ }
+ } else if (o_exp > 0) { /* decimal between digits */
ppc[1] = o_exp;
- ppc[2] = (intptr_t)(fmt + EMPTY_STRING_OFFSET);
ppc += 3;
+ s += o_exp;
+ i -= o_exp;
}
- } else if (o_exp > 0) { /* decimal between digits */
- ppc[1] = o_exp;
- ppc += 3;
- s += o_exp;
- i -= o_exp;
+ o_exp = -1;
}
- o_exp = -1;
- }
- if (PRINT_INFO_FLAG_VAL(info,alt)
- || (i)
- || ((o_mode != 'g')
+ if (PRINT_INFO_FLAG_VAL(info,alt)
+ || (i)
+ || ((o_mode != 'g')
#ifdef __UCLIBC_HAS_HEXADECIMAL_FLOATS__
- && (o_mode != 'a')
+ && (o_mode != 'a')
#endif /* __UCLIBC_HAS_HEXADECIMAL_FLOATS__ */
- && (preci > 0))
- ) {
- ppc[0] = FPO_STR_PREC;
+ && (preci > 0))
+ ) {
+ ppc[0] = FPO_STR_PREC;
#ifdef __LOCALE_C_ONLY
- ppc[1] = 1;
- ppc[2] = (intptr_t)(fmt + DECPT_OFFSET);
+ ppc[1] = 1;
+ ppc[2] = (intptr_t)(fmt + DECPT_OFFSET);
#else /* __LOCALE_C_ONLY */
#ifdef __UCLIBC_HAS_WCHAR__
if (PRINT_INFO_FLAG_VAL(info,wide)) {
@@ -569,39 +579,41 @@ size_t _fpmaxtostr(FILE * fp, __fpmax_t x, struct printf_info *info,
#endif /* __UCLIBC_HAS_WCHAR__ */
#endif /* __LOCALE_C_ONLY */
ppc += 3;
- }
-
- if (++o_exp < 0) { /* Have 0s right of decimal. */
- ppc[0] = FPO_ZERO_PAD;
- ppc[1] = -o_exp;
- ppc[2] = (intptr_t)(fmt + EMPTY_STRING_OFFSET);
- ppc += 3;
- }
- if (i) { /* Have digit(s) right of decimal. */
- ppc[0] = FPO_STR_PREC;
- ppc[1] = i;
- ppc[2] = (intptr_t)(s);
- ppc += 3;
- }
+ }
- if (((o_mode != 'g') || PRINT_INFO_FLAG_VAL(info,alt))
-#ifdef __UCLIBC_HAS_HEXADECIMAL_FLOATS__
- && !sufficient_precision
-#endif /* __UCLIBC_HAS_HEXADECIMAL_FLOATS__ */
- ) {
- i -= o_exp;
- if (i < preci) { /* Have 0s right of digits. */
- i = preci - i;
+ if (++o_exp < 0) { /* Have 0s right of decimal. */
ppc[0] = FPO_ZERO_PAD;
- ppc[1] = i;
+ ppc[1] = -o_exp;
ppc[2] = (intptr_t)(fmt + EMPTY_STRING_OFFSET);
ppc += 3;
}
+ if (i) { /* Have digit(s) right of decimal. */
+ ppc[0] = FPO_STR_PREC;
+ ppc[1] = i;
+ ppc[2] = (intptr_t)(s);
+ ppc += 3;
+ }
+
+ if (((o_mode != 'g') || PRINT_INFO_FLAG_VAL(info,alt))
+#ifdef __UCLIBC_HAS_HEXADECIMAL_FLOATS__
+ && !sufficient_precision
+#endif /* __UCLIBC_HAS_HEXADECIMAL_FLOATS__ */
+ ) {
+ i -= o_exp;
+ if (i < preci) { /* Have 0s right of digits. */
+ i = preci - i;
+ ppc[0] = FPO_ZERO_PAD;
+ ppc[1] = i;
+ ppc[2] = (intptr_t)(fmt + EMPTY_STRING_OFFSET);
+ ppc += 3;
+ }
+ }
}
/* Build exponent string. */
if (mode != 'f') {
char *p = exp_buf + sizeof(exp_buf);
+ int j;
char exp_char = *exp_buf;
char exp_sign = '+';
#ifdef __UCLIBC_HAS_HEXADECIMAL_FLOATS__
@@ -631,43 +643,46 @@ size_t _fpmaxtostr(FILE * fp, __fpmax_t x, struct printf_info *info,
}
EXIT_SPECIAL:
- ppc_last = ppc;
- ppc = pc_fwi + 4; /* Need width fields starting with second. */
- do {
- width -= *ppc;
- ppc += 3;
- } while (ppc < ppc_last);
+ {
+ int i;
+ ppc_last = ppc;
+ ppc = pc_fwi + 4; /* Need width fields starting with second. */
+ do {
+ width -= *ppc;
+ ppc += 3;
+ } while (ppc < ppc_last);
- ppc = pc_fwi;
- ppc[0] = FPO_STR_WIDTH;
- ppc[1] = i = ((*sign_str) != 0);
- ppc[2] = (intptr_t) sign_str;
+ ppc = pc_fwi;
+ ppc[0] = FPO_STR_WIDTH;
+ ppc[1] = i = ((*sign_str) != 0);
+ ppc[2] = (intptr_t) sign_str;
#ifdef __UCLIBC_HAS_HEXADECIMAL_FLOATS__
- if (((mode|0x20) == 'a') && (pc_fwi[3] >= 16)) { /* Hex sign handling. */
- /* Hex and not inf or nan, so prefix with 0x. */
- char *h = sign_str + i;
- *h = '0';
- *++h = 'x' - 'p' + *exp_buf;
- *++h = 0;
- ppc[1] = (i += 2);
- }
+ if (((mode|0x20) == 'a') && (pc_fwi[3] >= 16)) { /* Hex sign handling. */
+ /* Hex and not inf or nan, so prefix with 0x. */
+ char *h = sign_str + i;
+ *h = '0';
+ *++h = 'x' - 'p' + *exp_buf;
+ *++h = 0;
+ ppc[1] = (i += 2);
+ }
#endif /* __UCLIBC_HAS_HEXADECIMAL_FLOATS__ */
- if ((width -= i) > 0) {
- if (PRINT_INFO_FLAG_VAL(info,left)) { /* Left-justified. */
- ppc_last[0] = FPO_STR_WIDTH;
- ppc_last[1] = width;
- ppc_last[2] = (intptr_t)(fmt + EMPTY_STRING_OFFSET);
- ppc_last += 3;
- } else if (info->pad == '0') { /* 0 padding */
- ppc[4] += width; /* Pad second field. */
- } else {
- ppc[1] += width; /* Pad first (sign) field. */
+ if ((width -= i) > 0) {
+ if (PRINT_INFO_FLAG_VAL(info,left)) { /* Left-justified. */
+ ppc_last[0] = FPO_STR_WIDTH;
+ ppc_last[1] = width;
+ ppc_last[2] = (intptr_t)(fmt + EMPTY_STRING_OFFSET);
+ ppc_last += 3;
+ } else if (info->pad == '0') { /* 0 padding */
+ ppc[4] += width; /* Pad second field. */
+ } else {
+ ppc[1] += width; /* Pad first (sign) field. */
+ }
}
- }
- cnt = 0;
+ cnt = 0;
+ }
do {
#ifdef __UCLIBC_HAS_GLIBC_DIGIT_GROUPING__
@@ -685,7 +700,9 @@ size_t _fpmaxtostr(FILE * fp, __fpmax_t x, struct printf_info *info,
blk = nblk2;
} else if (len >= blk) { /* Enough digits for a group. */
/* printf("norm: len=%d blk=%d \"%.*s\"\n", len, blk, blk, gp); */
- fp_outfunc(fp, *ppc, blk, (intptr_t) gp);
+ if (fp_outfunc(fp, *ppc, blk, (intptr_t) gp) != blk) {
+ return -1;
+ }
assert(gp);
if (*gp) {
gp += blk;
@@ -695,7 +712,9 @@ size_t _fpmaxtostr(FILE * fp, __fpmax_t x, struct printf_info *info,
/* printf("trans: len=%d blk=%d \"%.*s\"\n", len, blk, len, gp); */
if (len) {
/* printf("len\n"); */
- fp_outfunc(fp, *ppc, len, (intptr_t) gp);
+ if (fp_outfunc(fp, *ppc, len, (intptr_t) gp) != len) {
+ return -1;
+ }
gp += len;
}
@@ -718,7 +737,9 @@ size_t _fpmaxtostr(FILE * fp, __fpmax_t x, struct printf_info *info,
}
--num_groups;
- fp_outfunc(fp, FPO_STR_PREC, tslen, (intptr_t) ts);
+ if (fp_outfunc(fp, FPO_STR_PREC, tslen, (intptr_t) ts) != tslen) {
+ return -1;
+ }
blk = nblk2;
/* printf("num_groups=%d blk=%d\n", num_groups, blk); */
@@ -727,8 +748,11 @@ size_t _fpmaxtostr(FILE * fp, __fpmax_t x, struct printf_info *info,
} else
#endif /* __UCLIBC_HAS_GLIBC_DIGIT_GROUPING__ */
-
- fp_outfunc(fp, *ppc, ppc[1], ppc[2]); /* NOTE: Remember 'else' above! */
+ { /* NOTE: Remember 'else' above! */
+ if (fp_outfunc(fp, *ppc, ppc[1], ppc[2]) != ppc[1]) {
+ return -1;
+ }
+ }
cnt += ppc[1];
ppc += 3;
diff --git a/libc/stdio/vfprintf.c b/libc/stdio/vfprintf.c
index dbc7c7cf2..10114f061 100644
--- a/libc/stdio/vfprintf.c
+++ b/libc/stdio/vfprintf.c
@@ -410,11 +410,11 @@ typedef struct {
only returns -1 if sets error indicator for the stream. */
#ifdef __STDIO_PRINTF_FLOAT
-typedef void (__fp_outfunc_t)(FILE *fp, intptr_t type, intptr_t len,
- intptr_t buf);
+typedef size_t (__fp_outfunc_t)(FILE *fp, intptr_t type, intptr_t len,
+ intptr_t buf);
-extern size_t _fpmaxtostr(FILE * fp, __fpmax_t x, struct printf_info *info,
- __fp_outfunc_t fp_outfunc);
+extern ssize_t _fpmaxtostr(FILE * fp, __fpmax_t x, struct printf_info *info,
+ __fp_outfunc_t fp_outfunc);
#endif
extern int _ppfs_init(ppfs_t *ppfs, const char *fmt0); /* validates */
@@ -1185,7 +1185,7 @@ int register_printf_function(int spec, printf_function handler,
* In other words, we don't currently support glibc's 'I' flag.
* We do accept it, but it is currently ignored. */
-static void _charpad(FILE * __restrict stream, int padchar, size_t numpad);
+static size_t _charpad(FILE * __restrict stream, int padchar, size_t numpad);
#ifdef L_vfprintf
@@ -1201,16 +1201,20 @@ static void _charpad(FILE * __restrict stream, int padchar, size_t numpad);
#ifdef __STDIO_PRINTF_FLOAT
-static void _fp_out_narrow(FILE *fp, intptr_t type, intptr_t len, intptr_t buf)
+static size_t _fp_out_narrow(FILE *fp, intptr_t type, intptr_t len, intptr_t buf)
{
+ size_t r = 0;
+
if (type & 0x80) { /* Some type of padding needed. */
int buflen = strlen((const char *) buf);
if ((len -= buflen) > 0) {
- _charpad(fp, (type & 0x7f), len);
+ if ((r = _charpad(fp, (type & 0x7f), len)) != len) {
+ return r;
+ }
}
len = buflen;
}
- OUTNSTR(fp, (const char *) buf, len);
+ return r + OUTNSTR(fp, (const char *) buf, len);
}
#endif /* __STDIO_PRINTF_FLOAT */
@@ -1226,12 +1230,12 @@ static void _fp_out_narrow(FILE *fp, intptr_t type, intptr_t len, intptr_t buf)
#define _outnwcs(stream, wstring, len) _wstdio_fwrite(wstring, len, stream)
#define FP_OUT _fp_out_wide
-static void _outnstr(FILE *stream, const char *s, size_t wclen)
+static size_t _outnstr(FILE *stream, const char *s, size_t wclen)
{
/* NOTE!!! len here is the number of wchars we want to generate!!! */
wchar_t wbuf[64];
mbstate_t mbstate;
- size_t todo, r;
+ size_t todo, r, n;
mbstate.__mask = 0;
todo = wclen;
@@ -1243,9 +1247,14 @@ static void _outnstr(FILE *stream, const char *s, size_t wclen)
: sizeof(wbuf)/sizeof(wbuf[0])),
&mbstate);
assert(((ssize_t)r) > 0);
- _outnwcs(stream, wbuf, r);
- todo -= r;
+ n = _outnwcs(stream, wbuf, r);
+ todo -= n;
+ if (n != r) {
+ break;
+ }
}
+
+ return wclen - todo;
}
#ifdef __STDIO_PRINTF_FLOAT
@@ -1259,16 +1268,19 @@ static void _outnstr(FILE *stream, const char *s, size_t wclen)
#define NUM_DIGIT_BLOCKS ((DECIMAL_DIG+DIGITS_PER_BLOCK-1)/DIGITS_PER_BLOCK)
#define BUF_SIZE ( 3 + NUM_DIGIT_BLOCKS * DIGITS_PER_BLOCK )
-static void _fp_out_wide(FILE *fp, intptr_t type, intptr_t len, intptr_t buf)
+static size_t _fp_out_wide(FILE *fp, intptr_t type, intptr_t len, intptr_t buf)
{
wchar_t wbuf[BUF_SIZE];
const char *s = (const char *) buf;
+ size_t r = 0;
int i;
if (type & 0x80) { /* Some type of padding needed */
int buflen = strlen(s);
if ((len -= buflen) > 0) {
- _charpad(fp, (type & 0x7f), len);
+ if ((r = _charpad(fp, (type & 0x7f), len)) != len) {
+ return r;
+ }
}
len = buflen;
}
@@ -1294,8 +1306,10 @@ static void _fp_out_wide(FILE *fp, intptr_t type, intptr_t len, intptr_t buf)
} while (++i < len);
- OUTNSTR(fp, wbuf, len);
+ r += OUTNSTR(fp, wbuf, len);
}
+
+ return r;
}
#endif /* __STDIO_PRINTF_FLOAT */
@@ -1385,16 +1399,19 @@ static int _ppwfs_init(register ppfs_t *ppfs, const wchar_t *fmt0)
#endif /* L_vfprintf */
-static void _charpad(FILE * __restrict stream, int padchar, size_t numpad)
+static size_t _charpad(FILE * __restrict stream, int padchar, size_t numpad)
{
+ size_t todo = numpad;
+
/* TODO -- Use a buffer to cut down on function calls... */
FMT_TYPE pad[1];
*pad = padchar;
- while (numpad) {
- OUTNSTR(stream, pad, 1);
- --numpad;
+ while (todo && (OUTNSTR(stream, pad, 1) == 1)) {
+ --todo;
}
+
+ return numpad - todo;
}
/* TODO -- Dynamically allocate work space to accomodate stack-poor archs? */
@@ -1583,13 +1600,18 @@ static int _do_one_spec(FILE * __restrict stream,
numfill = ((numfill > SLEN) ? numfill - SLEN : 0);
} else if (ppfs->conv_num <= CONV_A) { /* floating point */
#ifdef __STDIO_PRINTF_FLOAT
- *count +=
- _fpmaxtostr(stream,
- (__fpmax_t)
- (PRINT_INFO_FLAG_VAL(&(ppfs->info),is_long_double)
- ? *(long double *) *argptr
- : (long double) (* (double *) *argptr)),
- &ppfs->info, FP_OUT );
+ ssize_t nf;
+ nf = _fpmaxtostr(stream,
+ (__fpmax_t)
+ (PRINT_INFO_FLAG_VAL(&(ppfs->info),is_long_double)
+ ? *(long double *) *argptr
+ : (long double) (* (double *) *argptr)),
+ &ppfs->info, FP_OUT );
+ if (nf < 0) {
+ return -1;
+ }
+ *count += nf;
+
return 0;
#else /* __STDIO_PRINTF_FLOAT */
return -1; /* TODO -- try to continue? */
@@ -1757,18 +1779,24 @@ static int _do_one_spec(FILE * __restrict stream,
/* Now handle the output itself. */
if (!PRINT_INFO_FLAG_VAL(&(ppfs->info),left)) {
- _charpad(stream, ' ', numpad);
+ if (_charpad(stream, ' ', numpad) != numpad) {
+ return -1;
+ }
numpad = 0;
}
OUTPUT(stream, prefix + prefix_num);
- _charpad(stream, '0', numfill);
+ if (_charpad(stream, '0', numfill) != numfill) {
+ return -1;
+ }
#ifdef L_vfprintf
#ifdef __UCLIBC_HAS_WCHAR__
if (!ws) {
assert(s);
- _outnstr(stream, s, slen);
+ if (_outnstr(stream, s, slen) != slen) {
+ return -1;
+ }
} else { /* wide string */
size_t t;
mbstate.__mask = 0; /* Initialize the mbstate. */
@@ -1776,25 +1804,35 @@ static int _do_one_spec(FILE * __restrict stream,
t = (slen <= sizeof(buf)) ? slen : sizeof(buf);
t = wcsrtombs(buf, &ws, t, &mbstate);
assert (t != ((size_t)(-1)));
- _outnstr(stream, buf, t);
+ if (_outnstr(stream, buf, t) != t) {
+ return -1;
+ }
slen -= t;
}
}
#else /* __UCLIBC_HAS_WCHAR__ */
- _outnstr(stream, s, slen);
+ if (_outnstr(stream, s, slen) != slen) {
+ return -1;
+ }
#endif /* __UCLIBC_HAS_WCHAR__ */
#else /* L_vfprintf */
if (!ws) {
assert(s);
- _outnstr(stream, s, SLEN);
+ if (_outnstr(stream, s, SLEN) != SLEN) {
+ return -1;
+ }
} else {
- _outnwcs(stream, ws, SLEN);
+ if (_outnwcs(stream, ws, SLEN) != SLEN) {
+ return -1;
+ }
}
#endif /* L_vfprintf */
- _charpad(stream, ' ', numpad);
+ if (_charpad(stream, ' ', numpad) != numpad) {
+ return -1;
+ }
}
return 0;
@@ -1840,7 +1878,7 @@ int VFPRINTF (FILE * __restrict stream,
}
if (format-s) { /* output any literal text in format string */
- if ( (r = OUTNSTR(stream, s, format-s)) < 0) {
+ if ( (r = OUTNSTR(stream, s, format-s)) != (format-s)) {
count = -1;
break;
}