Merge "Fix the printf issue for 64 bits. The following case:"
This commit is contained in:
commit
b9bb48bf28
@ -51,7 +51,35 @@
|
|||||||
#include "local.h"
|
#include "local.h"
|
||||||
#include "fvwrite.h"
|
#include "fvwrite.h"
|
||||||
|
|
||||||
static void __find_arguments(const char *fmt0, va_list ap, va_list **argtable,
|
union arg {
|
||||||
|
int intarg;
|
||||||
|
unsigned int uintarg;
|
||||||
|
long longarg;
|
||||||
|
unsigned long ulongarg;
|
||||||
|
long long longlongarg;
|
||||||
|
unsigned long long ulonglongarg;
|
||||||
|
ptrdiff_t ptrdiffarg;
|
||||||
|
size_t sizearg;
|
||||||
|
size_t ssizearg;
|
||||||
|
intmax_t intmaxarg;
|
||||||
|
uintmax_t uintmaxarg;
|
||||||
|
void *pvoidarg;
|
||||||
|
char *pchararg;
|
||||||
|
signed char *pschararg;
|
||||||
|
short *pshortarg;
|
||||||
|
int *pintarg;
|
||||||
|
long *plongarg;
|
||||||
|
long long *plonglongarg;
|
||||||
|
ptrdiff_t *pptrdiffarg;
|
||||||
|
size_t *pssizearg;
|
||||||
|
intmax_t *pintmaxarg;
|
||||||
|
#ifdef FLOATING_POINT
|
||||||
|
double doublearg;
|
||||||
|
long double longdoublearg;
|
||||||
|
#endif
|
||||||
|
};
|
||||||
|
|
||||||
|
static int __find_arguments(const char *fmt0, va_list ap, union arg **argtable,
|
||||||
size_t *argtablesiz);
|
size_t *argtablesiz);
|
||||||
static int __grow_type_table(unsigned char **typetable, int *tablesize);
|
static int __grow_type_table(unsigned char **typetable, int *tablesize);
|
||||||
|
|
||||||
@ -169,13 +197,13 @@ vfprintf(FILE *fp, const char *fmt0, __va_list ap)
|
|||||||
int
|
int
|
||||||
__vfprintf(FILE *fp, const char *fmt0, __va_list ap)
|
__vfprintf(FILE *fp, const char *fmt0, __va_list ap)
|
||||||
{
|
{
|
||||||
char *fmt; /* format string */
|
char *fmt; /* format string */
|
||||||
int ch; /* character from fmt */
|
int ch; /* character from fmt */
|
||||||
int n, m, n2; /* handy integers (short term usage) */
|
int n, m, n2; /* handy integers (short term usage) */
|
||||||
char *cp; /* handy char pointer (short term usage) */
|
char *cp; /* handy char pointer (short term usage) */
|
||||||
char *cp_free = NULL; /* BIONIC: copy of cp to be freed after usage */
|
char *cp_free = NULL; /* BIONIC: copy of cp to be freed after usage */
|
||||||
struct __siov *iovp;/* for PRINT macro */
|
struct __siov *iovp; /* for PRINT macro */
|
||||||
int flags; /* flags as above */
|
int flags; /* flags as above */
|
||||||
int ret; /* return value accumulator */
|
int ret; /* return value accumulator */
|
||||||
int width; /* width from format (%8d), or 0 */
|
int width; /* width from format (%8d), or 0 */
|
||||||
int prec; /* precision from format (%.3d), or -1 */
|
int prec; /* precision from format (%.3d), or -1 */
|
||||||
@ -203,8 +231,8 @@ __vfprintf(FILE *fp, const char *fmt0, __va_list ap)
|
|||||||
struct __siov iov[NIOV];/* ... and individual io vectors */
|
struct __siov iov[NIOV];/* ... and individual io vectors */
|
||||||
char buf[BUF]; /* space for %c, %[diouxX], %[eEfgG] */
|
char buf[BUF]; /* space for %c, %[diouxX], %[eEfgG] */
|
||||||
char ox[2]; /* space for 0x hex-prefix */
|
char ox[2]; /* space for 0x hex-prefix */
|
||||||
va_list *argtable; /* args, built due to positional arg */
|
union arg *argtable; /* args, built due to positional arg */
|
||||||
va_list statargtable[STATIC_ARG_TBL_SIZE];
|
union arg statargtable[STATIC_ARG_TBL_SIZE];
|
||||||
size_t argtablesiz;
|
size_t argtablesiz;
|
||||||
int nextarg; /* 1-based argument index */
|
int nextarg; /* 1-based argument index */
|
||||||
va_list orgap; /* original argument pointer */
|
va_list orgap; /* original argument pointer */
|
||||||
@ -303,8 +331,8 @@ __vfprintf(FILE *fp, const char *fmt0, __va_list ap)
|
|||||||
* argument (and arguments must be gotten sequentially).
|
* argument (and arguments must be gotten sequentially).
|
||||||
*/
|
*/
|
||||||
#define GETARG(type) \
|
#define GETARG(type) \
|
||||||
(((argtable != NULL) ? (void)(ap = argtable[nextarg]) : (void)0), \
|
((argtable != NULL) ? *((type*)(&argtable[nextarg++])) : \
|
||||||
nextarg++, va_arg(ap, type))
|
(nextarg++, va_arg(ap, type)))
|
||||||
|
|
||||||
_SET_ORIENTATION(fp, -1);
|
_SET_ORIENTATION(fp, -1);
|
||||||
/* sorry, fprintf(read_only_file, "") returns EOF, not 0 */
|
/* sorry, fprintf(read_only_file, "") returns EOF, not 0 */
|
||||||
@ -548,15 +576,16 @@ reswitch: switch (ch) {
|
|||||||
size = expt;
|
size = expt;
|
||||||
if (prec || flags & ALT)
|
if (prec || flags & ALT)
|
||||||
size += prec + 1;
|
size += prec + 1;
|
||||||
} else /* "0.X" */
|
} else { /* "0.X" */
|
||||||
size = prec + 2;
|
size = prec + 2;
|
||||||
|
}
|
||||||
} else if (expt >= ndig) { /* fixed g fmt */
|
} else if (expt >= ndig) { /* fixed g fmt */
|
||||||
size = expt;
|
size = expt;
|
||||||
if (flags & ALT)
|
if (flags & ALT)
|
||||||
++size;
|
++size;
|
||||||
} else
|
} else {
|
||||||
size = ndig + (expt > 0 ?
|
size = ndig + (expt > 0 ? 1 : 2 - expt);
|
||||||
1 : 2 - expt);
|
}
|
||||||
|
|
||||||
if (softsign)
|
if (softsign)
|
||||||
sign = '-';
|
sign = '-';
|
||||||
@ -624,10 +653,12 @@ reswitch: switch (ch) {
|
|||||||
size = p - cp;
|
size = p - cp;
|
||||||
if (size > prec)
|
if (size > prec)
|
||||||
size = prec;
|
size = prec;
|
||||||
} else
|
} else {
|
||||||
size = prec;
|
size = prec;
|
||||||
} else
|
}
|
||||||
|
} else {
|
||||||
size = strlen(cp);
|
size = strlen(cp);
|
||||||
|
}
|
||||||
sign = '\0';
|
sign = '\0';
|
||||||
break;
|
break;
|
||||||
case 'U':
|
case 'U':
|
||||||
@ -793,11 +824,13 @@ number: if ((dprec = prec) >= 0)
|
|||||||
PRINT(ox, 2);
|
PRINT(ox, 2);
|
||||||
if (_double) {
|
if (_double) {
|
||||||
PRINT(cp, ndig-1);
|
PRINT(cp, ndig-1);
|
||||||
} else /* 0.[0..] */
|
} else {/* 0.[0..] */
|
||||||
/* __dtoa irregularity */
|
/* __dtoa irregularity */
|
||||||
PAD(ndig - 1, zeroes);
|
PAD(ndig - 1, zeroes);
|
||||||
} else /* XeYYY */
|
}
|
||||||
|
} else { /* XeYYY */
|
||||||
PRINT(cp, 1);
|
PRINT(cp, 1);
|
||||||
|
}
|
||||||
PRINT(expstr, expsize);
|
PRINT(expstr, expsize);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -874,15 +907,15 @@ error:
|
|||||||
* used since we are attempting to make snprintf thread safe, and alloca is
|
* used since we are attempting to make snprintf thread safe, and alloca is
|
||||||
* problematic since we have nested functions..)
|
* problematic since we have nested functions..)
|
||||||
*/
|
*/
|
||||||
static void
|
static int
|
||||||
__find_arguments(const char *fmt0, va_list ap, va_list **argtable,
|
__find_arguments(const char *fmt0, va_list ap, union arg **argtable,
|
||||||
size_t *argtablesiz)
|
size_t *argtablesiz)
|
||||||
{
|
{
|
||||||
char *fmt; /* format string */
|
char *fmt; /* format string */
|
||||||
int ch; /* character from fmt */
|
int ch; /* character from fmt */
|
||||||
int n, n2; /* handy integer (short term usage) */
|
int n, n2; /* handy integer (short term usage) */
|
||||||
char *cp; /* handy char pointer (short term usage) */
|
char *cp; /* handy char pointer (short term usage) */
|
||||||
int flags; /* flags as above */
|
int flags; /* flags as above */
|
||||||
unsigned char *typetable; /* table of types */
|
unsigned char *typetable; /* table of types */
|
||||||
unsigned char stattypetable[STATIC_ARG_TBL_SIZE];
|
unsigned char stattypetable[STATIC_ARG_TBL_SIZE];
|
||||||
int tablesize; /* current size of type table */
|
int tablesize; /* current size of type table */
|
||||||
@ -1105,86 +1138,89 @@ done:
|
|||||||
* Build the argument table.
|
* Build the argument table.
|
||||||
*/
|
*/
|
||||||
if (tablemax >= STATIC_ARG_TBL_SIZE) {
|
if (tablemax >= STATIC_ARG_TBL_SIZE) {
|
||||||
*argtablesiz = sizeof (va_list) * (tablemax + 1);
|
*argtablesiz = sizeof(union arg) * (tablemax + 1);
|
||||||
*argtable = (va_list *)mmap(NULL, *argtablesiz,
|
*argtable = mmap(NULL, *argtablesiz,
|
||||||
PROT_WRITE|PROT_READ, MAP_ANON|MAP_PRIVATE, -1, 0);
|
PROT_WRITE|PROT_READ, MAP_ANON|MAP_PRIVATE, -1, 0);
|
||||||
|
if (*argtable == MAP_FAILED)
|
||||||
|
return (-1);
|
||||||
}
|
}
|
||||||
|
|
||||||
#if 0
|
#if 0
|
||||||
/* XXX is this required? */
|
/* XXX is this required? */
|
||||||
(*argtable) [0] = NULL;
|
(*argtable)[0].intarg = 0;
|
||||||
#endif
|
#endif
|
||||||
for (n = 1; n <= tablemax; n++) {
|
for (n = 1; n <= tablemax; n++) {
|
||||||
va_copy((*argtable)[n], ap);
|
|
||||||
switch (typetable[n]) {
|
switch (typetable[n]) {
|
||||||
case T_UNUSED:
|
case T_UNUSED:
|
||||||
(void) va_arg(ap, int);
|
(*argtable)[n].intarg = va_arg(ap, int);
|
||||||
break;
|
break;
|
||||||
case T_SHORT:
|
case T_SHORT:
|
||||||
(void) va_arg(ap, int);
|
(*argtable)[n].intarg = va_arg(ap, int);
|
||||||
break;
|
break;
|
||||||
case T_U_SHORT:
|
case T_U_SHORT:
|
||||||
(void) va_arg(ap, int);
|
(*argtable)[n].intarg = va_arg(ap, int);
|
||||||
break;
|
break;
|
||||||
case TP_SHORT:
|
case TP_SHORT:
|
||||||
(void) va_arg(ap, short *);
|
(*argtable)[n].pshortarg = va_arg(ap, short *);
|
||||||
break;
|
break;
|
||||||
case T_INT:
|
case T_INT:
|
||||||
(void) va_arg(ap, int);
|
(*argtable)[n].intarg = va_arg(ap, int);
|
||||||
break;
|
break;
|
||||||
case T_U_INT:
|
case T_U_INT:
|
||||||
(void) va_arg(ap, unsigned int);
|
(*argtable)[n].uintarg = va_arg(ap, unsigned int);
|
||||||
break;
|
break;
|
||||||
case TP_INT:
|
case TP_INT:
|
||||||
(void) va_arg(ap, int *);
|
(*argtable)[n].pintarg = va_arg(ap, int *);
|
||||||
break;
|
break;
|
||||||
case T_LONG:
|
case T_LONG:
|
||||||
(void) va_arg(ap, long);
|
(*argtable)[n].longarg = va_arg(ap, long);
|
||||||
break;
|
break;
|
||||||
case T_U_LONG:
|
case T_U_LONG:
|
||||||
(void) va_arg(ap, unsigned long);
|
(*argtable)[n].ulongarg = va_arg(ap, unsigned long);
|
||||||
break;
|
break;
|
||||||
case TP_LONG:
|
case TP_LONG:
|
||||||
(void) va_arg(ap, long *);
|
(*argtable)[n].plongarg = va_arg(ap, long *);
|
||||||
break;
|
break;
|
||||||
case T_LLONG:
|
case T_LLONG:
|
||||||
(void) va_arg(ap, long long);
|
(*argtable)[n].longlongarg = va_arg(ap, long long);
|
||||||
break;
|
break;
|
||||||
case T_U_LLONG:
|
case T_U_LLONG:
|
||||||
(void) va_arg(ap, unsigned long long);
|
(*argtable)[n].ulonglongarg = va_arg(ap, unsigned long long);
|
||||||
break;
|
break;
|
||||||
case TP_LLONG:
|
case TP_LLONG:
|
||||||
(void) va_arg(ap, long long *);
|
(*argtable)[n].plonglongarg = va_arg(ap, long long *);
|
||||||
break;
|
break;
|
||||||
|
#ifdef FLOATING_POINT
|
||||||
case T_DOUBLE:
|
case T_DOUBLE:
|
||||||
(void) va_arg(ap, double);
|
(*argtable)[n].doublearg = va_arg(ap, double);
|
||||||
break;
|
break;
|
||||||
case T_LONG_DOUBLE:
|
case T_LONG_DOUBLE:
|
||||||
(void) va_arg(ap, long double);
|
(*argtable)[n].longdoublearg = va_arg(ap, long double);
|
||||||
break;
|
break;
|
||||||
|
#endif
|
||||||
case TP_CHAR:
|
case TP_CHAR:
|
||||||
(void) va_arg(ap, char *);
|
(*argtable)[n].pchararg = va_arg(ap, char *);
|
||||||
break;
|
break;
|
||||||
case TP_VOID:
|
case TP_VOID:
|
||||||
(void) va_arg(ap, void *);
|
(*argtable)[n].pvoidarg = va_arg(ap, void *);
|
||||||
break;
|
break;
|
||||||
case T_PTRINT:
|
case T_PTRINT:
|
||||||
(void) va_arg(ap, ptrdiff_t);
|
(*argtable)[n].ptrdiffarg = va_arg(ap, ptrdiff_t);
|
||||||
break;
|
break;
|
||||||
case TP_PTRINT:
|
case TP_PTRINT:
|
||||||
(void) va_arg(ap, ptrdiff_t *);
|
(*argtable)[n].pptrdiffarg = va_arg(ap, ptrdiff_t *);
|
||||||
break;
|
break;
|
||||||
case T_SIZEINT:
|
case T_SIZEINT:
|
||||||
(void) va_arg(ap, size_t);
|
(*argtable)[n].sizearg = va_arg(ap, size_t);
|
||||||
break;
|
break;
|
||||||
case T_SSIZEINT:
|
case T_SSIZEINT:
|
||||||
(void) va_arg(ap, ssize_t);
|
(*argtable)[n].ssizearg = va_arg(ap, ssize_t);
|
||||||
break;
|
break;
|
||||||
case TP_SSIZEINT:
|
case TP_SSIZEINT:
|
||||||
(void) va_arg(ap, ssize_t *);
|
(*argtable)[n].pssizearg = va_arg(ap, ssize_t *);
|
||||||
break;
|
break;
|
||||||
case TP_MAXINT:
|
case TP_MAXINT:
|
||||||
(void) va_arg(ap, intmax_t *);
|
(*argtable)[n].intmaxarg = va_arg(ap, intmax_t);
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -1193,6 +1229,7 @@ done:
|
|||||||
munmap(typetable, *argtablesiz);
|
munmap(typetable, *argtablesiz);
|
||||||
typetable = NULL;
|
typetable = NULL;
|
||||||
}
|
}
|
||||||
|
return (0);
|
||||||
}
|
}
|
||||||
|
|
||||||
/*
|
/*
|
||||||
@ -1205,24 +1242,24 @@ __grow_type_table(unsigned char **typetable, int *tablesize)
|
|||||||
int newsize = *tablesize * 2;
|
int newsize = *tablesize * 2;
|
||||||
|
|
||||||
if (*tablesize == STATIC_ARG_TBL_SIZE) {
|
if (*tablesize == STATIC_ARG_TBL_SIZE) {
|
||||||
*typetable = (unsigned char *)mmap(NULL,
|
*typetable = mmap(NULL, newsize, PROT_WRITE|PROT_READ,
|
||||||
sizeof (unsigned char) * newsize, PROT_WRITE|PROT_READ,
|
|
||||||
MAP_ANON|MAP_PRIVATE, -1, 0);
|
MAP_ANON|MAP_PRIVATE, -1, 0);
|
||||||
/* XXX unchecked */
|
if (*typetable == MAP_FAILED)
|
||||||
|
return (-1);
|
||||||
memcpy( *typetable, oldtable, *tablesize);
|
memcpy( *typetable, oldtable, *tablesize);
|
||||||
} else {
|
} else {
|
||||||
unsigned char *new = (unsigned char *)mmap(NULL,
|
unsigned char *new = mmap(NULL, newsize, PROT_WRITE|PROT_READ,
|
||||||
sizeof (unsigned char) * newsize, PROT_WRITE|PROT_READ,
|
|
||||||
MAP_ANON|MAP_PRIVATE, -1, 0);
|
MAP_ANON|MAP_PRIVATE, -1, 0);
|
||||||
|
if (new == MAP_FAILED)
|
||||||
|
return (-1);
|
||||||
memmove(new, *typetable, *tablesize);
|
memmove(new, *typetable, *tablesize);
|
||||||
munmap(*typetable, *tablesize);
|
munmap(*typetable, *tablesize);
|
||||||
*typetable = new;
|
*typetable = new;
|
||||||
/* XXX unchecked */
|
|
||||||
}
|
}
|
||||||
memset(*typetable + *tablesize, T_UNUSED, (newsize - *tablesize));
|
memset(*typetable + *tablesize, T_UNUSED, (newsize - *tablesize));
|
||||||
|
|
||||||
*tablesize = newsize;
|
*tablesize = newsize;
|
||||||
return(0);
|
return (0);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
@ -1256,7 +1293,7 @@ cvt(double value, int ndigits, int flags, char *sign, int *decpt, int ch,
|
|||||||
} else
|
} else
|
||||||
*sign = '\000';
|
*sign = '\000';
|
||||||
digits = __dtoa(value, mode, ndigits, decpt, &dsgn, &rve);
|
digits = __dtoa(value, mode, ndigits, decpt, &dsgn, &rve);
|
||||||
if ((ch != 'g' && ch != 'G') || flags & ALT) { /* Print trailing zeros */
|
if ((ch != 'g' && ch != 'G') || flags & ALT) {/* Print trailing zeros */
|
||||||
bp = digits + ndigits;
|
bp = digits + ndigits;
|
||||||
if (ch == 'f') {
|
if (ch == 'f') {
|
||||||
if (*digits == '0' && value)
|
if (*digits == '0' && value)
|
||||||
@ -1283,8 +1320,7 @@ exponent(char *p0, int exp, int fmtch)
|
|||||||
if (exp < 0) {
|
if (exp < 0) {
|
||||||
exp = -exp;
|
exp = -exp;
|
||||||
*p++ = '-';
|
*p++ = '-';
|
||||||
}
|
} else
|
||||||
else
|
|
||||||
*p++ = '+';
|
*p++ = '+';
|
||||||
t = expbuf + MAXEXP;
|
t = expbuf + MAXEXP;
|
||||||
if (exp > 9) {
|
if (exp > 9) {
|
||||||
@ -1292,9 +1328,9 @@ exponent(char *p0, int exp, int fmtch)
|
|||||||
*--t = to_char(exp % 10);
|
*--t = to_char(exp % 10);
|
||||||
} while ((exp /= 10) > 9);
|
} while ((exp /= 10) > 9);
|
||||||
*--t = to_char(exp);
|
*--t = to_char(exp);
|
||||||
for (; t < expbuf + MAXEXP; *p++ = *t++);
|
for (; t < expbuf + MAXEXP; *p++ = *t++)
|
||||||
}
|
/* nothing */;
|
||||||
else {
|
} else {
|
||||||
*p++ = '0';
|
*p++ = '0';
|
||||||
*p++ = to_char(exp);
|
*p++ = to_char(exp);
|
||||||
}
|
}
|
||||||
|
@ -297,6 +297,9 @@ TEST(stdio, snprintf_smoke) {
|
|||||||
|
|
||||||
snprintf(buf, sizeof(buf), "a_%g_b", 3.14);
|
snprintf(buf, sizeof(buf), "a_%g_b", 3.14);
|
||||||
EXPECT_STREQ("a_3.14_b", buf);
|
EXPECT_STREQ("a_3.14_b", buf);
|
||||||
|
|
||||||
|
snprintf(buf, sizeof(buf), "%1$s %1$s", "print_me_twice");
|
||||||
|
EXPECT_STREQ("print_me_twice print_me_twice", buf);
|
||||||
}
|
}
|
||||||
|
|
||||||
TEST(stdio, snprintf_d_INT_MAX) {
|
TEST(stdio, snprintf_d_INT_MAX) {
|
||||||
|
Loading…
Reference in New Issue
Block a user