Skip to content
Open
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
164 changes: 128 additions & 36 deletions common/snprintf.c
Original file line number Diff line number Diff line change
Expand Up @@ -53,10 +53,16 @@

#include "config.h"

#include <limits.h>
#include <string.h>
#include <ctype.h>
#include <sys/types.h>

#ifdef TEST_SNPRINTF
extern int printf (const char *format, ...);
extern int sprintf (char *str, const char *format, ...);
#endif

#if !defined(HAVE_SNPRINTF) || !defined(HAVE_VSNPRINTF)

/* Define this as a fall through, HAVE_STDARG_H is probably already set */
Expand Down Expand Up @@ -112,7 +118,8 @@ static void dopr (char *buffer, size_t maxlen, const char *format,
static void fmtstr (char *buffer, size_t *currlen, size_t maxlen,
char *value, int flags, int min, int max);
static void fmtint (char *buffer, size_t *currlen, size_t maxlen,
long value, int base, int min, int max, int flags);
unsigned LLONG uvalue, int negative,
int base, int min, int max, int flags);
static void fmtfp (char *buffer, size_t *currlen, size_t maxlen,
LDOUBLE fvalue, int min, int max, int flags);
static void dopr_outch (char *buffer, size_t *currlen, size_t maxlen, char c );
Expand Down Expand Up @@ -169,6 +176,7 @@ static void dopr (char *buffer, size_t maxlen, const char *format, va_list args)
{
char ch;
LLONG value;
unsigned LLONG uvalue;
LDOUBLE fvalue;
char *strvalue;
int min;
Expand Down Expand Up @@ -307,39 +315,40 @@ static void dopr (char *buffer, size_t maxlen, const char *format, va_list args)
value = va_arg (args, LLONG);
else
value = va_arg (args, int);
fmtint (buffer, &currlen, maxlen, value, 10, min, max, flags);
fmtint (buffer, &currlen, maxlen, (unsigned LLONG)value,
(value < 0), 10, min, max, flags);
break;
case 'o':
flags |= DP_F_UNSIGNED;
if (cflags == DP_C_SHORT)
#ifdef C89PLUS
value = (unsigned short int)va_arg (args, unsigned int);
uvalue = (unsigned short int)va_arg (args, unsigned int);
#else
value = va_arg (args, unsigned short int);
uvalue = va_arg (args, unsigned short int);
#endif
else if (cflags == DP_C_LONG)
value = (long)va_arg (args, unsigned long int);
uvalue = va_arg (args, unsigned long int);
else if (cflags == DP_C_LLONG)
value = (long)va_arg (args, unsigned LLONG);
uvalue = va_arg (args, unsigned LLONG);
else
value = (long)va_arg (args, unsigned int);
fmtint (buffer, &currlen, maxlen, value, 8, min, max, flags);
uvalue = va_arg (args, unsigned int);
fmtint (buffer, &currlen, maxlen, uvalue, 0, 8, min, max, flags);
break;
case 'u':
flags |= DP_F_UNSIGNED;
if (cflags == DP_C_SHORT)
#ifdef C89PLUS
value = (unsigned short int)va_arg (args, unsigned int);
uvalue = (unsigned short int)va_arg (args, unsigned int);
#else
value = va_arg (args, unsigned short int);
uvalue = va_arg (args, unsigned short int);
#endif
else if (cflags == DP_C_LONG)
value = (long)va_arg (args, unsigned long int);
uvalue = va_arg (args, unsigned long int);
else if (cflags == DP_C_LLONG)
value = (LLONG)va_arg (args, unsigned LLONG);
uvalue = va_arg (args, unsigned LLONG);
else
value = (long)va_arg (args, unsigned int);
fmtint (buffer, &currlen, maxlen, value, 10, min, max, flags);
uvalue = va_arg (args, unsigned int);
fmtint (buffer, &currlen, maxlen, uvalue, 0, 10, min, max, flags);
break;
case 'X':
flags |= DP_F_UP;
Expand All @@ -349,17 +358,17 @@ static void dopr (char *buffer, size_t maxlen, const char *format, va_list args)
flags |= DP_F_UNSIGNED;
if (cflags == DP_C_SHORT)
#ifdef C89PLUS
value = (unsigned short int)va_arg (args, unsigned int);
uvalue = (unsigned short int)va_arg (args, unsigned int);
#else
value = va_arg (args, unsigned short int);
uvalue = va_arg (args, unsigned short int);
#endif
else if (cflags == DP_C_LONG)
value = (long)va_arg (args, unsigned long int);
uvalue = va_arg (args, unsigned long int);
else if (cflags == DP_C_LLONG)
value = (LLONG)va_arg (args, unsigned LLONG);
uvalue = va_arg (args, unsigned LLONG);
else
value = (long)va_arg (args, unsigned int);
fmtint (buffer, &currlen, maxlen, value, 16, min, max, flags);
uvalue = va_arg (args, unsigned int);
fmtint (buffer, &currlen, maxlen, uvalue, 0, 16, min, max, flags);
break;
case 'f':
if (cflags == DP_C_LDOUBLE)
Expand Down Expand Up @@ -400,13 +409,9 @@ static void dopr (char *buffer, size_t maxlen, const char *format, va_list args)
break;
case 'p':
strvalue = va_arg (args, void *);
/* FIXME: in 64-bit (and Windows-targeted) builds this code yields:
* warning: cast from pointer to integer of different size
* so probably prints a truncated pointer value. Should check
* if sizeof(void*) == sizeof(long) and output e.g. two pieces
* (lower and upper long for bytes of the pointer).
*/
fmtint (buffer, &currlen, maxlen, (long) strvalue, 16, min, max, flags);
flags |= DP_F_UNSIGNED;
fmtint (buffer, &currlen, maxlen,
(unsigned LLONG)(size_t) strvalue, 0, 16, min, max, flags);
break;
case 'n':
if (cflags == DP_C_SHORT)
Expand Down Expand Up @@ -503,11 +508,11 @@ static void fmtstr (char *buffer, size_t *currlen, size_t maxlen,
/* Have to handle DP_F_NUM (ie 0x and 0 alternates) */

static void fmtint (char *buffer, size_t *currlen, size_t maxlen,
long value, int base, int min, int max, int flags)
unsigned LLONG uvalue, int negative,
int base, int min, int max, int flags)
{
int signvalue = 0;
unsigned long uvalue;
char convert[20];
char convert[sizeof(uvalue) * CHAR_BIT + 1];
int place = 0;
int spadlen = 0; /* amount to space pad */
int zpadlen = 0; /* amount to zero pad */
Expand All @@ -516,13 +521,14 @@ static void fmtint (char *buffer, size_t *currlen, size_t maxlen,
if (max < 0)
max = 0;

uvalue = value;

if(!(flags & DP_F_UNSIGNED))
{
if( value < 0 ) {
if( negative ) {
signvalue = '-';
uvalue = -value;
/* uvalue holds the signed argument converted to unsigned
* (defined modulo arithmetic); unsigned negation yields its
* magnitude without overflow, even for LLONG_MIN. */
uvalue = -uvalue;
Comment thread
jimklimov marked this conversation as resolved.
}
else
if (flags & DP_F_PLUS) /* Do a sign (+/i) */
Expand All @@ -539,8 +545,7 @@ static void fmtint (char *buffer, size_t *currlen, size_t maxlen,
(caps? "0123456789ABCDEF":"0123456789abcdef")
[uvalue % (unsigned)base ];
uvalue = (uvalue / (unsigned)base );
} while(uvalue && (place < 20));
if (place == 20) place--;
} while(uvalue && (place < (int)(sizeof(convert) - 1)));
convert[place] = 0;

zpadlen = max - place;
Expand Down Expand Up @@ -942,6 +947,18 @@ static void dopr_outch (char *buffer, size_t *currlen, size_t maxlen, char c)
NULL
};
long int_nums[] = { -1, 134, 91340, 341, 0203, 0};
static int pointer_num;
#ifdef HAVE_LONG_LONG_INT
LLONG llong_nums[] = { ((LLONG)1 << 32) + 1, LLONG_MIN };
char *ullong_fmt[] = { "%llu", "%llx", "%llo", NULL };
unsigned LLONG ullong_nums[] = {
ULLONG_MAX,
(unsigned LLONG)1 << (sizeof(unsigned LLONG) * CHAR_BIT - 1),
ULLONG_MAX
};
#endif
char *ptr1;
char *ptr2;
int x, y;
int fail = 0;
int num = 0;
Expand Down Expand Up @@ -975,6 +992,81 @@ static void dopr_outch (char *buffer, size_t *currlen, size_t maxlen, char c)
}
num++;
}

snprintf (buf1, sizeof (buf1), "%u", UINT_MAX);
sprintf (buf2, "%u", UINT_MAX);
if (strcmp (buf1, buf2))
{
printf("snprintf doesn't match Format: %%u\n\tsnprintf = %s\n\tsprintf = %s\n",
buf1, buf2);
fail++;
}
num++;

snprintf (buf1, sizeof (buf1), "%lu", ULONG_MAX);
sprintf (buf2, "%lu", ULONG_MAX);
if (strcmp (buf1, buf2))
{
printf("snprintf doesn't match Format: %%lu\n\tsnprintf = %s\n\tsprintf = %s\n",
buf1, buf2);
fail++;
}
num++;

snprintf (buf1, sizeof (buf1), "%p", (void *)&pointer_num);
sprintf (buf2, "%p", (void *)&pointer_num);
ptr1 = buf1;
ptr2 = buf2;
if (ptr1[0] == '0' && (ptr1[1] == 'x' || ptr1[1] == 'X'))
ptr1 += 2;
if (ptr2[0] == '0' && (ptr2[1] == 'x' || ptr2[1] == 'X'))
ptr2 += 2;
while (ptr1[0] == '0' && ptr1[1] != '\0')
ptr1++;
while (ptr2[0] == '0' && ptr2[1] != '\0')
ptr2++;
while (*ptr1 && *ptr2
&& tolower ((unsigned char)*ptr1) == tolower ((unsigned char)*ptr2))
{
ptr1++;
ptr2++;
}
if (*ptr1 || *ptr2)
{
printf("snprintf doesn't match Format: %%p\n\tsnprintf = %s\n\tsprintf = %s\n",
buf1, buf2);
fail++;
}
num++;

#ifdef HAVE_LONG_LONG_INT
for (x = 0; x < 2; x++)
{
snprintf (buf1, sizeof (buf1), "%lld", llong_nums[x]);
sprintf (buf2, "%lld", llong_nums[x]);
if (strcmp (buf1, buf2))
{
printf("snprintf doesn't match Format: %%lld\n\tsnprintf = %s\n\tsprintf = %s\n",
buf1, buf2);
fail++;
}
num++;
}

for (x = 0; ullong_fmt[x] != NULL; x++)
{
snprintf (buf1, sizeof (buf1), ullong_fmt[x], ullong_nums[x]);
sprintf (buf2, ullong_fmt[x], ullong_nums[x]);
if (strcmp (buf1, buf2))
{
printf("snprintf doesn't match Format: %s\n\tsnprintf = %s\n\tsprintf = %s\n",
ullong_fmt[x], buf1, buf2);
fail++;
}
num++;
}
#endif
printf ("%d tests failed out of %d.\n", fail, num);
return fail;
}
#endif /* SNPRINTF_TEST */
Loading