[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]
[PATCH v2 3/8] Update snprintf.c
From: |
Ladislav Michl |
Subject: |
[PATCH v2 3/8] Update snprintf.c |
Date: |
Tue, 4 Dec 2018 22:22:07 +0100 |
User-agent: |
Mutt/1.10.1 (2018-07-13) |
From: Fabrizio Gennari <address@hidden>
Update to the latest version from Samba's repository,
https://git.samba.org/?p=samba.git;a=blob;f=lib/replace/snprintf.c;hb=9f03cf91235641d017e31abc3856df994e6d1cf2
---
No changes
ChangeLog | 3 +
common/snprintf.c | 1184 +++++++++++++++++++++++++++++++++------------
2 files changed, 870 insertions(+), 317 deletions(-)
diff --git a/ChangeLog b/ChangeLog
index ed6d42ff..ad462734 100644
--- a/ChangeLog
+++ b/ChangeLog
@@ -121,6 +121,9 @@
o since Linux filesystems are case-sensitive, and MinGW-W64
provides lower case names for Win32 header files, use lower
case names in #include directives
+ o update snprintf.c (replacement of snprintf for systems where
+ it is not C99-compatible, such as Win32) to the latest
+ version from Samba's repository
0.6.31
======
diff --git a/common/snprintf.c b/common/snprintf.c
index b1222806..1f5f93e4 100644
--- a/common/snprintf.c
+++ b/common/snprintf.c
@@ -1,3 +1,7 @@
+/*
+ * NOTE: If you change this file, please merge it into rsync, samba, etc.
+ */
+
/*
* Copyright Patrick Powell 1995
* This code is based on code written by Patrick Powell (address@hidden)
@@ -30,14 +34,14 @@
* probably requires libm on most operating systems. Don't yet
* support the exponent (e,E) and sigfig (g,G). Also, fmtint()
* was pretty badly broken, it just wasn't being exercised in ways
- * which showed it, so that's been fixed. Also, formated the code
+ * which showed it, so that's been fixed. Also, formatted the code
* to mutt conventions, and removed dead code left over from the
* original. Also, there is now a builtin-test, just compile with:
* gcc -DTEST_SNPRINTF -o snprintf snprintf.c -lm
* and run snprintf for results.
- *
+ *
* Thomas Roessler <address@hidden> 01/27/98 for mutt 0.89i
- * The PGP code was using unsigned hexadecimal formats.
+ * The PGP code was using unsigned hexadecimal formats.
* Unfortunately, unsigned formats simply didn't work.
*
* Michael Elkins <address@hidden> 03/05/98 for mutt 0.90.8
@@ -53,47 +57,76 @@
* got rid of fcvt code (twas buggy and made testing harder)
* added C99 semantics
*
+ * date: 2002/12/19 19:56:31; author: herb; state: Exp; lines: +2 -0
+ * actually print args for %g and %e
+ *
+ * date: 2002/06/03 13:37:52; author: jmcd; state: Exp; lines: +8 -0
+ * Since includes.h isn't included here, VA_COPY has to be defined here. I
don't
+ * see any include file that is guaranteed to be here, so I'm defining it
+ * locally. Fixes AIX and Solaris builds.
+ *
+ * date: 2002/06/03 03:07:24; author: tridge; state: Exp; lines: +5 -13
+ * put the ifdef for HAVE_VA_COPY in one place rather than in lots of
+ * functions
+ *
+ * date: 2002/05/17 14:51:22; author: jmcd; state: Exp; lines: +21 -4
+ * Fix usage of va_list passed as an arg. Use __va_copy before using it
+ * when it exists.
+ *
+ * date: 2002/04/16 22:38:04; author: idra; state: Exp; lines: +20 -14
+ * Fix incorrect zpadlen handling in fmtfp.
+ * Thanks to Ollie Oldham <address@hidden> for spotting it.
+ * few mods to make it easier to compile the tests.
+ * addedd the "Ollie" test to the floating point ones.
+ *
+ * Martin Pool (address@hidden) April 2003
+ * Remove NO_CONFIG_H so that the test case can be built within a source
+ * tree with less trouble.
+ * Remove unnecessary SAFE_FREE() definition.
+ *
+ * Martin Pool (address@hidden) May 2003
+ * Put in a prototype for dummy_snprintf() to quiet compiler warnings.
+ *
+ * Move #endif to make sure VA_COPY, LDOUBLE, etc are defined even
+ * if the C library has some snprintf functions already.
+ *
+ * Darren Tucker (address@hidden) 2005
+ * Fix bug allowing read overruns of the source string with "%.*s"
+ * Usually harmless unless the read runs outside the process' allocation
+ * (eg if your malloc does guard pages) in which case it will segfault.
+ * From OpenSSH. Also added test for same.
+ *
+ * Simo Sorce (address@hidden) Jan 2006
+ *
+ * Add support for position independent parameters
+ * fix fmtstr now it conforms to sprintf wrt min.max
+ *
**************************************************************/
-#ifndef NO_CONFIG_H /* for some tests */
-# include "config.h"
-#endif
-
#include "compat.h"
-#define snprintf __dummy_snprintf
-
-#if defined(WIN32) && !defined(CYGWIN)
-# include <stdio.h>
-# include <stddef.h>
-#endif
-
-#ifdef HAVE_STRING_H
-# include <string.h>
-#endif
-
-#ifdef HAVE_STRINGS_H
-# include <strings.h>
-#endif
-#ifdef HAVE_CTYPE_H
-# include <ctype.h>
-#endif
-#include <sys/types.h>
-#ifdef HAVE_STDARG_H
-# include <stdarg.h>
-#endif
-#ifdef HAVE_STDLIB_H
-# include <stdlib.h>
-#endif
+#ifdef TEST_SNPRINTF /* need math library headers for testing */
-#undef snprintf
+/* In test mode, we pretend that this system doesn't have any snprintf
+ * functions, regardless of what config.h says. */
+# undef HAVE_SNPRINTF
+# undef HAVE_VSNPRINTF
+# undef HAVE_C99_VSNPRINTF
+# undef HAVE_ASPRINTF
+# undef HAVE_VASPRINTF
+# include <math.h>
+#endif /* TEST_SNPRINTF */
#if defined(HAVE_SNPRINTF) && defined(HAVE_VSNPRINTF) &&
defined(HAVE_C99_VSNPRINTF)
/* only include stdio.h if we are not re-defining snprintf or vsnprintf */
-# include <stdio.h>
-/* make the compiler happy with an empty file */
-void dummy_snprintf(void) {}
-#else
+#include <stdio.h>
+ /* make the compiler happy with an empty file */
+ void dummy_snprintf(void);
+ void dummy_snprintf(void) {}
+#endif /* HAVE_SNPRINTF, etc */
+
+/* yes this really must be a ||. Don't muck with this (tridge) */
+#if !defined(HAVE_VSNPRINTF) || !defined(HAVE_C99_VSNPRINTF)
#ifdef HAVE_LONG_DOUBLE
#define LDOUBLE long double
@@ -101,26 +134,22 @@ void dummy_snprintf(void) {}
#define LDOUBLE double
#endif
-#ifdef HAVE_LONG_LONG_INT
+#ifdef HAVE_LONG_LONG
#define LLONG long long
#else
#define LLONG long
#endif
-/* free memory if the pointer is valid and zero the pointer */
-#ifndef SAFE_FREE
-#define SAFE_FREE(x) do { if ((x) != NULL) {free((x)); (x)=NULL;} } while(0)
+#ifndef VA_COPY
+#ifdef HAVE_VA_COPY
+#define VA_COPY(dest, src) va_copy(dest, src)
+#else
+#ifdef HAVE___VA_COPY
+#define VA_COPY(dest, src) __va_copy(dest, src)
+#else
+#define VA_COPY(dest, src) (dest) = (src)
+#endif
#endif
-
-static size_t dopr(char *buffer, size_t maxlen, const char *format,
- va_list args);
-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);
-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);
/*
* dopr(): poor man's version of doprintf
@@ -146,66 +175,145 @@ static void dopr_outch(char *buffer, size_t *currlen,
size_t maxlen, char c);
#define DP_F_UNSIGNED (1 << 6)
/* Conversion Flags */
-#define DP_C_SHORT 1
-#define DP_C_LONG 2
-#define DP_C_LDOUBLE 3
-#define DP_C_LLONG 4
+#define DP_C_CHAR 1
+#define DP_C_SHORT 2
+#define DP_C_LONG 3
+#define DP_C_LDOUBLE 4
+#define DP_C_LLONG 5
+#define DP_C_SIZET 6
+
+/* Chunk types */
+#define CNK_FMT_STR 0
+#define CNK_INT 1
+#define CNK_OCTAL 2
+#define CNK_UINT 3
+#define CNK_HEX 4
+#define CNK_FLOAT 5
+#define CNK_CHAR 6
+#define CNK_STRING 7
+#define CNK_PTR 8
+#define CNK_NUM 9
+#define CNK_PRCNT 10
#define char_to_int(p) ((p)- '0')
#ifndef MAX
#define MAX(p,q) (((p) >= (q)) ? (p) : (q))
#endif
-static size_t dopr(char *buffer, size_t maxlen, const char *format, va_list
args)
-{
- char ch;
+struct pr_chunk {
+ int type; /* chunk type */
+ int num; /* parameter number */
+ int min;
+ int max;
+ int flags;
+ int cflags;
+ int start;
+ int len;
LLONG value;
LDOUBLE fvalue;
char *strvalue;
- int min;
- int max;
+ void *pnum;
+ struct pr_chunk *min_star;
+ struct pr_chunk *max_star;
+ struct pr_chunk *next;
+};
+
+struct pr_chunk_x {
+ struct pr_chunk **chunks;
+ int num;
+};
+
+static int dopr(char *buffer, size_t maxlen, const char *format,
+ va_list args_in);
+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,
+ LLONG value, 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);
+static struct pr_chunk *new_chunk(void);
+static int add_cnk_list_entry(struct pr_chunk_x **list,
+ int max_num, struct pr_chunk *chunk);
+
+static int dopr(char *buffer, size_t maxlen, const char *format, va_list
args_in)
+{
+ char ch;
int state;
- int flags;
- int cflags;
+ int pflag;
+ int pnum;
+ int pfirst;
size_t currlen;
-
+ va_list args;
+ const char *base;
+ struct pr_chunk *chunks = NULL;
+ struct pr_chunk *cnk = NULL;
+ struct pr_chunk_x *clist = NULL;
+ int max_pos;
+ int ret = -1;
+
+ VA_COPY(args, args_in);
+
state = DP_S_DEFAULT;
- currlen = flags = cflags = min = 0;
- max = -1;
+ pfirst = 1;
+ pflag = 0;
+ pnum = 0;
+
+ max_pos = 0;
+ base = format;
ch = *format++;
+ /* retrieve the string structure as chunks */
while (state != DP_S_DONE) {
- if (ch == '\0')
+ if (ch == '\0')
state = DP_S_DONE;
switch(state) {
case DP_S_DEFAULT:
- if (ch == '%')
+
+ if (cnk) {
+ cnk->next = new_chunk();
+ cnk = cnk->next;
+ } else {
+ cnk = new_chunk();
+ }
+ if (!cnk) goto done;
+ if (!chunks) chunks = cnk;
+
+ if (ch == '%') {
state = DP_S_FLAGS;
- else
- dopr_outch (buffer, &currlen, maxlen, ch);
- ch = *format++;
+ ch = *format++;
+ } else {
+ cnk->type = CNK_FMT_STR;
+ cnk->start = format - base -1;
+ while ((ch != '\0') && (ch != '%')) ch =
*format++;
+ cnk->len = format - base - cnk->start -1;
+ }
break;
case DP_S_FLAGS:
switch (ch) {
case '-':
- flags |= DP_F_MINUS;
+ cnk->flags |= DP_F_MINUS;
ch = *format++;
break;
case '+':
- flags |= DP_F_PLUS;
+ cnk->flags |= DP_F_PLUS;
ch = *format++;
break;
case ' ':
- flags |= DP_F_SPACE;
+ cnk->flags |= DP_F_SPACE;
ch = *format++;
break;
case '#':
- flags |= DP_F_NUM;
+ cnk->flags |= DP_F_NUM;
ch = *format++;
break;
case '0':
- flags |= DP_F_ZERO;
+ cnk->flags |= DP_F_ZERO;
+ ch = *format++;
+ break;
+ case 'I':
+ /* internationalization not supported yet */
ch = *format++;
break;
default:
@@ -215,13 +323,51 @@ static size_t dopr(char *buffer, size_t maxlen, const
char *format, va_list args
break;
case DP_S_MIN:
if (isdigit((unsigned char)ch)) {
- min = 10*min + char_to_int (ch);
+ cnk->min = 10 * cnk->min + char_to_int (ch);
+ ch = *format++;
+ } else if (ch == '$') {
+ if (!pfirst && !pflag) {
+ /* parameters must be all positioned or
none */
+ goto done;
+ }
+ if (pfirst) {
+ pfirst = 0;
+ pflag = 1;
+ }
+ if (cnk->min == 0) /* what ?? */
+ goto done;
+ cnk->num = cnk->min;
+ cnk->min = 0;
ch = *format++;
} else if (ch == '*') {
- min = va_arg (args, int);
+ if (pfirst) pfirst = 0;
+ cnk->min_star = new_chunk();
+ if (!cnk->min_star) /* out of memory :-( */
+ goto done;
+ cnk->min_star->type = CNK_INT;
+ if (pflag) {
+ int num;
+ ch = *format++;
+ if (!isdigit((unsigned char)ch)) {
+ /* parameters must be all
positioned or none */
+ goto done;
+ }
+ for (num = 0; isdigit((unsigned
char)ch); ch = *format++) {
+ num = 10 * num +
char_to_int(ch);
+ }
+ cnk->min_star->num = num;
+ if (ch != '$') /* what ?? */
+ goto done;
+ } else {
+ cnk->min_star->num = ++pnum;
+ }
+ max_pos = add_cnk_list_entry(&clist, max_pos,
cnk->min_star);
+ if (max_pos == 0) /* out of memory :-( */
+ goto done;
ch = *format++;
state = DP_S_DOT;
} else {
+ if (pfirst) pfirst = 0;
state = DP_S_DOT;
}
break;
@@ -229,18 +375,51 @@ static size_t dopr(char *buffer, size_t maxlen, const
char *format, va_list args
if (ch == '.') {
state = DP_S_MAX;
ch = *format++;
- } else {
+ } else {
state = DP_S_MOD;
}
break;
case DP_S_MAX:
if (isdigit((unsigned char)ch)) {
- if (max < 0)
- max = 0;
- max = 10*max + char_to_int (ch);
+ if (cnk->max < 0)
+ cnk->max = 0;
+ cnk->max = 10 * cnk->max + char_to_int (ch);
+ ch = *format++;
+ } else if (ch == '$') {
+ if (!pfirst && !pflag) {
+ /* parameters must be all positioned or
none */
+ goto done;
+ }
+ if (cnk->max <= 0) /* what ?? */
+ goto done;
+ cnk->num = cnk->max;
+ cnk->max = -1;
ch = *format++;
} else if (ch == '*') {
- max = va_arg (args, int);
+ cnk->max_star = new_chunk();
+ if (!cnk->max_star) /* out of memory :-( */
+ goto done;
+ cnk->max_star->type = CNK_INT;
+ if (pflag) {
+ int num;
+ ch = *format++;
+ if (!isdigit((unsigned char)ch)) {
+ /* parameters must be all
positioned or none */
+ goto done;
+ }
+ for (num = 0; isdigit((unsigned
char)ch); ch = *format++) {
+ num = 10 * num +
char_to_int(ch);
+ }
+ cnk->max_star->num = num;
+ if (ch != '$') /* what ?? */
+ goto done;
+ } else {
+ cnk->max_star->num = ++pnum;
+ }
+ max_pos = add_cnk_list_entry(&clist, max_pos,
cnk->max_star);
+ if (max_pos == 0) /* out of memory :-( */
+ goto done;
+
ch = *format++;
state = DP_S_MOD;
} else {
@@ -250,19 +429,31 @@ static size_t dopr(char *buffer, size_t maxlen, const
char *format, va_list args
case DP_S_MOD:
switch (ch) {
case 'h':
- cflags = DP_C_SHORT;
+ cnk->cflags = DP_C_SHORT;
ch = *format++;
+ if (ch == 'h') {
+ cnk->cflags = DP_C_CHAR;
+ ch = *format++;
+ }
break;
case 'l':
- cflags = DP_C_LONG;
+ cnk->cflags = DP_C_LONG;
ch = *format++;
if (ch == 'l') { /* It's a long long */
- cflags = DP_C_LLONG;
+ cnk->cflags = DP_C_LLONG;
ch = *format++;
}
break;
+ case 'j':
+ cnk->cflags = DP_C_LLONG;
+ ch = *format++;
+ break;
case 'L':
- cflags = DP_C_LDOUBLE;
+ cnk->cflags = DP_C_LDOUBLE;
+ ch = *format++;
+ break;
+ case 'z':
+ cnk->cflags = DP_C_SIZET;
ch = *format++;
break;
default:
@@ -271,131 +462,65 @@ static size_t dopr(char *buffer, size_t maxlen, const
char *format, va_list args
state = DP_S_CONV;
break;
case DP_S_CONV:
+ if (cnk->num == 0) cnk->num = ++pnum;
+ max_pos = add_cnk_list_entry(&clist, max_pos, cnk);
+ if (max_pos == 0) /* out of memory :-( */
+ goto done;
+
switch (ch) {
case 'd':
case 'i':
- if (cflags == DP_C_SHORT)
- value = va_arg (args, int);
- else if (cflags == DP_C_LONG)
- value = va_arg (args, long int);
- else if (cflags == DP_C_LLONG)
- value = va_arg (args, LLONG);
- else
- value = va_arg (args, int);
- fmtint (buffer, &currlen, maxlen, value, 10,
min, max, flags);
+ cnk->type = CNK_INT;
break;
case 'o':
- flags |= DP_F_UNSIGNED;
- if (cflags == DP_C_SHORT)
- value = va_arg (args, unsigned int);
- else if (cflags == DP_C_LONG)
- value = (long)va_arg (args, unsigned
long int);
- else if (cflags == DP_C_LLONG)
- value = (long)va_arg (args, unsigned
LLONG);
- else
- value = (long)va_arg (args, unsigned
int);
- fmtint (buffer, &currlen, maxlen, value, 8,
min, max, flags);
+ cnk->type = CNK_OCTAL;
+ cnk->flags |= DP_F_UNSIGNED;
break;
case 'u':
- flags |= DP_F_UNSIGNED;
- if (cflags == DP_C_SHORT)
- value = va_arg (args, unsigned int);
- else if (cflags == DP_C_LONG)
- value = (long)va_arg (args, unsigned
long int);
- else if (cflags == DP_C_LLONG)
- value = (LLONG)va_arg (args, unsigned
LLONG);
- else
- value = (long)va_arg (args, unsigned
int);
- fmtint (buffer, &currlen, maxlen, value, 10,
min, max, flags);
+ cnk->type = CNK_UINT;
+ cnk->flags |= DP_F_UNSIGNED;
break;
case 'X':
- flags |= DP_F_UP;
+ cnk->flags |= DP_F_UP;
case 'x':
- flags |= DP_F_UNSIGNED;
- if (cflags == DP_C_SHORT)
- value = va_arg (args, unsigned int);
- else if (cflags == DP_C_LONG)
- value = (long)va_arg (args, unsigned
long int);
- else if (cflags == DP_C_LLONG)
- value = (LLONG)va_arg (args, unsigned
LLONG);
- else
- value = (long)va_arg (args, unsigned
int);
- fmtint (buffer, &currlen, maxlen, value, 16,
min, max, flags);
- break;
- case 'f':
- if (cflags == DP_C_LDOUBLE)
- fvalue = va_arg (args, LDOUBLE);
- else
- fvalue = va_arg (args, double);
- /* um, floating point? */
- fmtfp (buffer, &currlen, maxlen, fvalue, min,
max, flags);
+ cnk->type = CNK_HEX;
+ cnk->flags |= DP_F_UNSIGNED;
break;
+ case 'A':
+ /* hex float not supported yet */
case 'E':
- flags |= DP_F_UP;
- case 'e':
- if (cflags == DP_C_LDOUBLE)
- fvalue = va_arg (args, LDOUBLE);
- else
- fvalue = va_arg (args, double);
- break;
case 'G':
- flags |= DP_F_UP;
+ case 'F':
+ cnk->flags |= DP_F_UP;
+ case 'a':
+ /* hex float not supported yet */
+ case 'e':
+ case 'f':
case 'g':
- if (cflags == DP_C_LDOUBLE)
- fvalue = va_arg (args, LDOUBLE);
- else
- fvalue = va_arg (args, double);
+ cnk->type = CNK_FLOAT;
break;
case 'c':
- dopr_outch (buffer, &currlen, maxlen, va_arg
(args, int));
+ cnk->type = CNK_CHAR;
break;
case 's':
- strvalue = va_arg (args, char *);
- if (!strvalue) strvalue = "(NULL)";
- if (max == -1) {
- max = strlen(strvalue);
- }
- if (min > 0 && max >= 0 && min > max) max = min;
- fmtstr (buffer, &currlen, maxlen, strvalue,
flags, min, max);
+ cnk->type = CNK_STRING;
break;
case 'p':
- strvalue = va_arg (args, void *);
- fmtint (buffer, &currlen, maxlen, (long)
strvalue, 16, min, max, flags);
+ cnk->type = CNK_PTR;
+ cnk->flags |= DP_F_UNSIGNED;
break;
case 'n':
- if (cflags == DP_C_SHORT) {
- short int *num;
- num = va_arg (args, short int *);
- *num = currlen;
- } else if (cflags == DP_C_LONG) {
- long int *num;
- num = va_arg (args, long int *);
- *num = (long int)currlen;
- } else if (cflags == DP_C_LLONG) {
- LLONG *num;
- num = va_arg (args, LLONG *);
- *num = (LLONG)currlen;
- } else {
- int *num;
- num = va_arg (args, int *);
- *num = currlen;
- }
+ cnk->type = CNK_NUM;
break;
case '%':
- dopr_outch (buffer, &currlen, maxlen, ch);
- break;
- case 'w':
- /* not supported yet, treat as next char */
- ch = *format++;
+ cnk->type = CNK_PRCNT;
break;
default:
- /* Unknown, skip */
- break;
+ /* Unknown, bail out*/
+ goto done;
}
ch = *format++;
state = DP_S_DEFAULT;
- flags = cflags = min = 0;
- max = -1;
break;
case DP_S_DONE:
break;
@@ -404,14 +529,237 @@ static size_t dopr(char *buffer, size_t maxlen, const
char *format, va_list args
break; /* some picky compilers need this */
}
}
+
+ /* retrieve the format arguments */
+ for (pnum = 0; pnum < max_pos; pnum++) {
+ int i;
+
+ if (clist[pnum].num == 0) {
+ /* ignoring a parameter should not be permitted
+ * all parameters must be matched at least once
+ * BUT seem some system ignore this rule ...
+ * at least my glibc based system does --SSS
+ */
+#ifdef DEBUG_SNPRINTF
+ printf("parameter at position %d not used\n", pnum+1);
+#endif
+ /* eat the parameter */
+ va_arg (args, int);
+ continue;
+ }
+ for (i = 1; i < clist[pnum].num; i++) {
+ if (clist[pnum].chunks[0]->type !=
clist[pnum].chunks[i]->type) {
+ /* nooo noo no!
+ * all the references to a parameter
+ * must be of the same type
+ */
+ goto done;
+ }
+ }
+ cnk = clist[pnum].chunks[0];
+ switch (cnk->type) {
+ case CNK_INT:
+ if (cnk->cflags == DP_C_SHORT)
+ cnk->value = va_arg (args, int);
+ else if (cnk->cflags == DP_C_LONG)
+ cnk->value = va_arg (args, long int);
+ else if (cnk->cflags == DP_C_LLONG)
+ cnk->value = va_arg (args, LLONG);
+ else if (cnk->cflags == DP_C_SIZET)
+ cnk->value = va_arg (args, ssize_t);
+ else
+ cnk->value = va_arg (args, int);
+
+ for (i = 1; i < clist[pnum].num; i++) {
+ clist[pnum].chunks[i]->value = cnk->value;
+ }
+ break;
+
+ case CNK_OCTAL:
+ case CNK_UINT:
+ case CNK_HEX:
+ if (cnk->cflags == DP_C_SHORT)
+ cnk->value = va_arg (args, unsigned int);
+ else if (cnk->cflags == DP_C_LONG)
+ cnk->value = (unsigned long int)va_arg (args,
unsigned long int);
+ else if (cnk->cflags == DP_C_LLONG)
+ cnk->value = (LLONG)va_arg (args, unsigned
LLONG);
+ else if (cnk->cflags == DP_C_SIZET)
+ cnk->value = (size_t)va_arg (args, size_t);
+ else
+ cnk->value = (unsigned int)va_arg (args,
unsigned int);
+
+ for (i = 1; i < clist[pnum].num; i++) {
+ clist[pnum].chunks[i]->value = cnk->value;
+ }
+ break;
+
+ case CNK_FLOAT:
+ if (cnk->cflags == DP_C_LDOUBLE)
+ cnk->fvalue = va_arg (args, LDOUBLE);
+ else
+ cnk->fvalue = va_arg (args, double);
+
+ for (i = 1; i < clist[pnum].num; i++) {
+ clist[pnum].chunks[i]->fvalue = cnk->fvalue;
+ }
+ break;
+
+ case CNK_CHAR:
+ cnk->value = va_arg (args, int);
+
+ for (i = 1; i < clist[pnum].num; i++) {
+ clist[pnum].chunks[i]->value = cnk->value;
+ }
+ break;
+
+ case CNK_STRING:
+ cnk->strvalue = va_arg (args, char *);
+ if (!cnk->strvalue) cnk->strvalue = "(NULL)";
+
+ for (i = 1; i < clist[pnum].num; i++) {
+ clist[pnum].chunks[i]->strvalue = cnk->strvalue;
+ }
+ break;
+
+ case CNK_PTR:
+ cnk->strvalue = va_arg (args, void *);
+ for (i = 1; i < clist[pnum].num; i++) {
+ clist[pnum].chunks[i]->strvalue = cnk->strvalue;
+ }
+ break;
+
+ case CNK_NUM:
+ if (cnk->cflags == DP_C_CHAR)
+ cnk->pnum = va_arg (args, char *);
+ else if (cnk->cflags == DP_C_SHORT)
+ cnk->pnum = va_arg (args, short int *);
+ else if (cnk->cflags == DP_C_LONG)
+ cnk->pnum = va_arg (args, long int *);
+ else if (cnk->cflags == DP_C_LLONG)
+ cnk->pnum = va_arg (args, LLONG *);
+ else if (cnk->cflags == DP_C_SIZET)
+ cnk->pnum = va_arg (args, ssize_t *);
+ else
+ cnk->pnum = va_arg (args, int *);
+
+ for (i = 1; i < clist[pnum].num; i++) {
+ clist[pnum].chunks[i]->pnum = cnk->pnum;
+ }
+ break;
+
+ case CNK_PRCNT:
+ break;
+
+ default:
+ /* what ?? */
+ goto done;
+ }
+ }
+ /* print out the actual string from chunks */
+ currlen = 0;
+ cnk = chunks;
+ while (cnk) {
+ int len, min, max;
+
+ if (cnk->min_star) min = cnk->min_star->value;
+ else min = cnk->min;
+ if (cnk->max_star) max = cnk->max_star->value;
+ else max = cnk->max;
+
+ switch (cnk->type) {
+
+ case CNK_FMT_STR:
+ if (maxlen != 0 && maxlen > currlen) {
+ if (maxlen > (currlen + cnk->len)) len =
cnk->len;
+ else len = maxlen - currlen;
+
+ memcpy(&(buffer[currlen]), &(base[cnk->start]),
len);
+ }
+ currlen += cnk->len;
+
+ break;
+
+ case CNK_INT:
+ case CNK_UINT:
+ fmtint (buffer, &currlen, maxlen, cnk->value, 10, min,
max, cnk->flags);
+ break;
+
+ case CNK_OCTAL:
+ fmtint (buffer, &currlen, maxlen, cnk->value, 8, min,
max, cnk->flags);
+ break;
+
+ case CNK_HEX:
+ fmtint (buffer, &currlen, maxlen, cnk->value, 16, min,
max, cnk->flags);
+ break;
+
+ case CNK_FLOAT:
+ fmtfp (buffer, &currlen, maxlen, cnk->fvalue, min, max,
cnk->flags);
+ break;
+
+ case CNK_CHAR:
+ dopr_outch (buffer, &currlen, maxlen, cnk->value);
+ break;
+
+ case CNK_STRING:
+ if (max == -1) {
+ max = strlen(cnk->strvalue);
+ }
+ fmtstr (buffer, &currlen, maxlen, cnk->strvalue,
cnk->flags, min, max);
+ break;
+
+ case CNK_PTR:
+ fmtint (buffer, &currlen, maxlen,
(long)(cnk->strvalue), 16, min, max, cnk->flags);
+ break;
+
+ case CNK_NUM:
+ if (cnk->cflags == DP_C_CHAR)
+ *((char *)(cnk->pnum)) = (char)currlen;
+ else if (cnk->cflags == DP_C_SHORT)
+ *((short int *)(cnk->pnum)) = (short
int)currlen;
+ else if (cnk->cflags == DP_C_LONG)
+ *((long int *)(cnk->pnum)) = (long int)currlen;
+ else if (cnk->cflags == DP_C_LLONG)
+ *((LLONG *)(cnk->pnum)) = (LLONG)currlen;
+ else if (cnk->cflags == DP_C_SIZET)
+ *((ssize_t *)(cnk->pnum)) = (ssize_t)currlen;
+ else
+ *((int *)(cnk->pnum)) = (int)currlen;
+ break;
+
+ case CNK_PRCNT:
+ dopr_outch (buffer, &currlen, maxlen, '%');
+ break;
+
+ default:
+ /* what ?? */
+ goto done;
+ }
+ cnk = cnk->next;
+ }
if (maxlen != 0) {
- if (currlen < maxlen - 1)
+ if (currlen < maxlen - 1)
buffer[currlen] = '\0';
- else if (maxlen > 0)
+ else if (maxlen > 0)
buffer[maxlen - 1] = '\0';
}
-
- return currlen;
+ ret = currlen;
+
+done:
+ va_end(args);
+
+ while (chunks) {
+ cnk = chunks->next;
+ free(chunks);
+ chunks = cnk;
+ }
+ if (clist) {
+ for (pnum = 0; pnum < max_pos; pnum++) {
+ if (clist[pnum].chunks) free(clist[pnum].chunks);
+ }
+ free(clist);
+ }
+ return ret;
}
static void fmtstr(char *buffer, size_t *currlen, size_t maxlen,
@@ -427,37 +775,35 @@ static void fmtstr(char *buffer, size_t *currlen, size_t
maxlen,
value = "<NULL>";
}
- for (strln = 0; value[strln]; ++strln); /* strlen */
+ for (strln = 0; strln < max && value[strln]; ++strln); /* strlen */
padlen = min - strln;
- if (padlen < 0)
+ if (padlen < 0)
padlen = 0;
- if (flags & DP_F_MINUS)
+ if (flags & DP_F_MINUS)
padlen = -padlen; /* Left Justify */
- while ((padlen > 0) && (cnt < max)) {
+ while (padlen > 0) {
dopr_outch (buffer, currlen, maxlen, ' ');
--padlen;
- ++cnt;
}
while (*value && (cnt < max)) {
dopr_outch (buffer, currlen, maxlen, *value++);
++cnt;
}
- while ((padlen < 0) && (cnt < max)) {
+ while (padlen < 0) {
dopr_outch (buffer, currlen, maxlen, ' ');
++padlen;
- ++cnt;
}
}
/* 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)
+ LLONG value, int base, int min, int max, int flags)
{
int signvalue = 0;
- unsigned long uvalue;
- char convert[20];
+ unsigned LLONG uvalue;
+ char convert[22+1]; /* 64-bit value in octal: 22 digits + \0 */
int place = 0;
int spadlen = 0; /* amount to space pad */
int zpadlen = 0; /* amount to zero pad */
@@ -479,7 +825,7 @@ static void fmtint(char *buffer, size_t *currlen, size_t
maxlen,
signvalue = ' ';
}
}
-
+
if (flags & DP_F_UP) caps = 1; /* Should characters be upper case? */
do {
@@ -487,8 +833,8 @@ 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 < sizeof(convert)));
+ if (place == sizeof(convert)) place--;
convert[place] = 0;
zpadlen = max - place;
@@ -499,7 +845,7 @@ static void fmtint(char *buffer, size_t *currlen, size_t
maxlen,
zpadlen = MAX(zpadlen, spadlen);
spadlen = 0;
}
- if (flags & DP_F_MINUS)
+ if (flags & DP_F_MINUS)
spadlen = -spadlen; /* Left Justifty */
#ifdef DEBUG_SNPRINTF
@@ -514,7 +860,7 @@ static void fmtint(char *buffer, size_t *currlen, size_t
maxlen,
}
/* Sign */
- if (signvalue)
+ if (signvalue)
dopr_outch (buffer, currlen, maxlen, signvalue);
/* Zeros */
@@ -526,9 +872,9 @@ static void fmtint(char *buffer, size_t *currlen, size_t
maxlen,
}
/* Digits */
- while (place > 0)
+ while (place > 0)
dopr_outch (buffer, currlen, maxlen, convert[--place]);
-
+
/* Left Justified spaces */
while (spadlen < 0) {
dopr_outch (buffer, currlen, maxlen, ' ');
@@ -554,7 +900,7 @@ static LDOUBLE POW10(int exp)
result *= 10;
exp--;
}
-
+
return result;
}
@@ -574,7 +920,7 @@ static LLONG ROUND(LDOUBLE value)
static double my_modf(double x0, double *iptr)
{
int i;
- long l;
+ LLONG l=0;
double x = x0;
double f = 1.0;
@@ -598,7 +944,7 @@ static double my_modf(double x0, double *iptr)
ret = my_modf(x0-l*f, &i2);
(*iptr) = l*f + i2;
return ret;
- }
+ }
(*iptr) = l;
return x - (*iptr);
@@ -615,14 +961,14 @@ static void fmtfp (char *buffer, size_t *currlen, size_t
maxlen,
int iplace = 0;
int fplace = 0;
int padlen = 0; /* amount to pad */
- int zpadlen = 0;
+ int zpadlen = 0;
int caps = 0;
- int index;
+ int idx;
double intpart;
double fracpart;
double temp;
-
- /*
+
+ /*
* AIX manpage says the default is 0, but Solaris says the default
* is 6, and sprintf on AIX defaults to 6
*/
@@ -650,12 +996,12 @@ static void fmtfp (char *buffer, size_t *currlen, size_t
maxlen,
if (max == 0) ufvalue += 0.5; /* if max = 0 we must round */
#endif
- /*
- * Sorry, we only support 16 digits past the decimal because of our
+ /*
+ * Sorry, we only support 9 digits past the decimal because of our
* conversion method
*/
- if (max > 16)
- max = 16;
+ if (max > 9)
+ max = 9;
/* We "cheat" by converting the fractional part to integer by
* multiplying by a factor of 10
@@ -674,14 +1020,13 @@ static void fmtfp (char *buffer, size_t *currlen, size_t
maxlen,
/* Convert integer part */
do {
- temp = intpart;
- my_modf(intpart*0.1, &intpart);
- temp = temp*0.1;
- index = (int) ((temp -intpart +0.05)* 10.0);
- /* index = (int) (((double)(temp*0.1) -intpart +0.05) *10.0); */
- /* printf ("%llf, %f, %x\n", temp, intpart, index); */
+ temp = intpart*0.1;
+ my_modf(temp, &intpart);
+ idx = (int) ((temp -intpart +0.05)* 10.0);
+ /* idx = (int) (((double)(temp*0.1) -intpart +0.05) *10.0); */
+ /* printf ("%llf, %f, %x\n", temp, intpart, idx); */
iconvert[iplace++] =
- (caps? "0123456789ABCDEF":"0123456789abcdef")[index];
+ (caps? "0123456789ABCDEF":"0123456789abcdef")[idx];
} while (intpart && (iplace < 311));
if (iplace == 311) iplace--;
iconvert[iplace] = 0;
@@ -690,26 +1035,25 @@ static void fmtfp (char *buffer, size_t *currlen, size_t
maxlen,
if (fracpart)
{
do {
- temp = fracpart;
- my_modf(fracpart*0.1, &fracpart);
- temp = temp*0.1;
- index = (int) ((temp -fracpart +0.05)* 10.0);
- /* index = (int) ((((temp/10) -fracpart) +0.05) *10); */
- /* printf ("%lf, %lf, %ld\n", temp, fracpart, index); */
+ temp = fracpart*0.1;
+ my_modf(temp, &fracpart);
+ idx = (int) ((temp -fracpart +0.05)* 10.0);
+ /* idx = (int) ((((temp/10) -fracpart) +0.05) *10); */
+ /* printf ("%lf, %lf, %ld\n", temp, fracpart, idx ); */
fconvert[fplace++] =
- (caps? "0123456789ABCDEF":"0123456789abcdef")[index];
+ (caps? "0123456789ABCDEF":"0123456789abcdef")[idx];
} while(fracpart && (fplace < 311));
if (fplace == 311) fplace--;
}
fconvert[fplace] = 0;
-
+
/* -1 for decimal point, another -1 if we are printing a sign */
- padlen = min - iplace - max - 1 - ((signvalue) ? 1 : 0);
+ padlen = min - iplace - max - 1 - ((signvalue) ? 1 : 0);
zpadlen = max - fplace;
if (zpadlen < 0) zpadlen = 0;
- if (padlen < 0)
+ if (padlen < 0)
padlen = 0;
- if (flags & DP_F_MINUS)
+ if (flags & DP_F_MINUS)
padlen = -padlen; /* Left Justifty */
if ((flags & DP_F_ZERO) && (padlen > 0)) {
@@ -727,10 +1071,10 @@ static void fmtfp (char *buffer, size_t *currlen, size_t
maxlen,
dopr_outch (buffer, currlen, maxlen, ' ');
--padlen;
}
- if (signvalue)
+ if (signvalue)
dopr_outch (buffer, currlen, maxlen, signvalue);
- while (iplace > 0)
+ while (iplace > 0)
dopr_outch (buffer, currlen, maxlen, iconvert[--iplace]);
#ifdef DEBUG_SNPRINTF
@@ -744,14 +1088,14 @@ static void fmtfp (char *buffer, size_t *currlen, size_t
maxlen,
if (max > 0) {
dopr_outch (buffer, currlen, maxlen, '.');
- while (fplace > 0)
+ while (zpadlen > 0) {
+ dopr_outch (buffer, currlen, maxlen, '0');
+ --zpadlen;
+ }
+
+ while (fplace > 0)
dopr_outch (buffer, currlen, maxlen,
fconvert[--fplace]);
}
-
- while (zpadlen > 0) {
- dopr_outch (buffer, currlen, maxlen, '0');
- --zpadlen;
- }
while (padlen < 0) {
dopr_outch (buffer, currlen, maxlen, ' ');
@@ -767,59 +1111,178 @@ static void dopr_outch(char *buffer, size_t *currlen,
size_t maxlen, char c)
(*currlen)++;
}
-/* yes this really must be a ||. Don't muck with this (tridge) */
-#if !defined(HAVE_VSNPRINTF) || !defined(HAVE_C99_VSNPRINTF)
-int vsnprintf (char *str, size_t count, const char *fmt, va_list args)
+static struct pr_chunk *new_chunk(void) {
+ struct pr_chunk *new_c = (struct pr_chunk *)malloc(sizeof(struct
pr_chunk));
+
+ if (!new_c)
+ return NULL;
+
+ new_c->type = 0;
+ new_c->num = 0;
+ new_c->min = 0;
+ new_c->min_star = NULL;
+ new_c->max = -1;
+ new_c->max_star = NULL;
+ new_c->flags = 0;
+ new_c->cflags = 0;
+ new_c->start = 0;
+ new_c->len = 0;
+ new_c->value = 0;
+ new_c->fvalue = 0;
+ new_c->strvalue = NULL;
+ new_c->pnum = NULL;
+ new_c->next = NULL;
+
+ return new_c;
+}
+
+static int add_cnk_list_entry(struct pr_chunk_x **list,
+ int max_num, struct pr_chunk *chunk) {
+ struct pr_chunk_x *l;
+ struct pr_chunk **c;
+ int max;
+ int cnum;
+ int i, pos;
+
+ if (chunk->num > max_num) {
+ max = chunk->num;
+
+ if (*list == NULL) {
+ l = (struct pr_chunk_x *)malloc(sizeof(struct
pr_chunk_x) * max);
+ pos = 0;
+ } else {
+ l = (struct pr_chunk_x *)realloc(*list, sizeof(struct
pr_chunk_x) * max);
+ pos = max_num;
+ }
+ if (l == NULL) {
+ for (i = 0; i < max; i++) {
+ if ((*list)[i].chunks) free((*list)[i].chunks);
+ }
+ return 0;
+ }
+ for (i = pos; i < max; i++) {
+ l[i].chunks = NULL;
+ l[i].num = 0;
+ }
+ } else {
+ l = *list;
+ max = max_num;
+ }
+
+ i = chunk->num - 1;
+ cnum = l[i].num + 1;
+ if (l[i].chunks == NULL) {
+ c = (struct pr_chunk **)malloc(sizeof(struct pr_chunk *) *
cnum);
+ } else {
+ c = (struct pr_chunk **)realloc(l[i].chunks, sizeof(struct
pr_chunk *) * cnum);
+ }
+ if (c == NULL) {
+ for (i = 0; i < max; i++) {
+ if (l[i].chunks) free(l[i].chunks);
+ }
+ return 0;
+ }
+ c[l[i].num] = chunk;
+ l[i].chunks = c;
+ l[i].num = cnum;
+
+ *list = l;
+ return max;
+}
+
+ int rep_vsnprintf (char *str, size_t count, const char *fmt, va_list args)
{
return dopr(str, count, fmt, args);
}
#endif
-/* yes this really must be a ||. Don't muck wiith this (tridge)
+/* yes this really must be a ||. Don't muck with this (tridge)
*
* The logic for these two is that we need our own definition if the
* OS *either* has no definition of *sprintf, or if it does have one
- * that doesn't work properly according to the autoconf test. Perhaps
- * these should really be smb_snprintf to avoid conflicts with buggy
- * linkers? -- mbp
+ * that doesn't work properly according to the autoconf test.
*/
-#if !defined(HAVE_SNPRINTF) || !defined(HAVE_C99_SNPRINTF)
-int snprintf(char *str,size_t count,const char *fmt,...)
+#if !defined(HAVE_SNPRINTF) || !defined(HAVE_C99_VSNPRINTF)
+ int rep_snprintf(char *str,size_t count,const char *fmt,...)
{
size_t ret;
va_list ap;
-
+
va_start(ap, fmt);
ret = vsnprintf(str, count, fmt, ap);
va_end(ap);
-#ifdef WIN32
- str[count-1] = 0; /* Windows vsnprintf does NOT truncate str. We
do it manually. */
+ return ret;
+}
#endif
+
+#ifndef HAVE_C99_VSNPRINTF
+ int rep_printf(const char *fmt, ...)
+{
+ va_list ap;
+ int ret;
+ char *s;
+
+ s = NULL;
+ va_start(ap, fmt);
+ ret = vasprintf(&s, fmt, ap);
+ va_end(ap);
+
+ if (s) {
+ fwrite(s, 1, strlen(s), stdout);
+ }
+ free(s);
+
return ret;
}
#endif
+#ifndef HAVE_C99_VSNPRINTF
+ int rep_fprintf(FILE *stream, const char *fmt, ...)
+{
+ va_list ap;
+ int ret;
+ char *s;
+
+ s = NULL;
+ va_start(ap, fmt);
+ ret = vasprintf(&s, fmt, ap);
+ va_end(ap);
+
+ if (s) {
+ fwrite(s, 1, strlen(s), stream);
+ }
+ free(s);
+
+ return ret;
+}
#endif
-#ifndef HAVE_VASPRINTF
-int vasprintf(char **ptr, const char *format, va_list ap)
+#endif
+
+#if !defined(HAVE_VASPRINTF) || !defined(HAVE_C99_VSNPRINTF)
+ int rep_vasprintf(char **ptr, const char *format, va_list ap)
{
int ret;
-
- ret = vsnprintf(NULL, 0, format, ap);
- if (ret <= 0) return ret;
+ va_list ap2;
+
+ VA_COPY(ap2, ap);
+ ret = vsnprintf(NULL, 0, format, ap2);
+ va_end(ap2);
+ if (ret < 0) return ret;
(*ptr) = (char *)malloc(ret+1);
if (!*ptr) return -1;
- ret = vsnprintf(*ptr, ret+1, format, ap);
+
+ VA_COPY(ap2, ap);
+ ret = vsnprintf(*ptr, ret+1, format, ap2);
+ va_end(ap2);
return ret;
}
#endif
-
-#ifndef HAVE_ASPRINTF
-int asprintf(char **ptr, const char *format, ...)
+#if !defined(HAVE_ASPRINTF) || !defined(HAVE_C99_VSNPRINTF)
+ int rep_asprintf(char **ptr, const char *format, ...)
{
va_list ap;
int ret;
@@ -833,28 +1296,16 @@ int asprintf(char **ptr, const char *format, ...)
}
#endif
-#ifndef HAVE_VSYSLOG
-#ifdef HAVE_SYSLOG
-void vsyslog (int facility_priority, char *format, va_list arglist)
-{
- char *msg = NULL;
- vasprintf(&msg, format, arglist);
- if (!msg)
- return;
- syslog(facility_priority, "%s", msg);
- SAFE_FREE(msg);
-}
-#endif /* HAVE_SYSLOG */
-#endif /* HAVE_VSYSLOG */
-
#ifdef TEST_SNPRINTF
-int sprintf(char *str,const char *fmt,...);
+ int sprintf(char *str,const char *fmt,...);
+ int printf(const char *fmt,...);
-int main (void)
+ int main (void)
{
char buf1[1024];
char buf2[1024];
+ char *buf3;
char *fp_fmt[] = {
"%1.1f",
"%-1.5f",
@@ -870,11 +1321,13 @@ int main (void)
"%3.2f",
"%.0f",
"%f",
- "-16.16f",
+ "%-8.8f",
+ "%-9.9f",
NULL
};
- double fp_nums[] = { 6442452944.1234, -1.5, 134.21, 91340.2, 341.1234,
0203.9, 0.96, 0.996,
- 0.9996, 1.996, 4.136, 0};
+ double fp_nums[] = { 6442452944.1234, -1.5, 134.21, 91340.2, 341.1234,
203.9, 0.96, 0.996,
+ 0.9996, 1.996, 4.136, 5.030201, 0.00205,
+ /* END LIST */ 0};
char *int_fmt[] = {
"%-1.5d",
"%1.5d",
@@ -888,14 +1341,16 @@ int main (void)
"%d",
NULL
};
- long int_nums[] = { -1, 134, 91340, 341, 0203, 0};
+ long int_nums[] = { -1, 134, 91340, 341, 0203, 1234567890, 0};
char *str_fmt[] = {
- "10.5s",
- "5.10s",
- "10.1s",
- "0.10s",
- "10.0s",
- "1.10s",
+ "%10.5s",
+ "%-10.5s",
+ "%5.10s",
+ "%-5.10s",
+ "%10.1s",
+ "%0.10s",
+ "%10.0s",
+ "%1.10s",
"%s",
"%.1s",
"%.10s",
@@ -903,24 +1358,35 @@ int main (void)
NULL
};
char *str_vals[] = {"hello", "a", "", "a longer string", NULL};
+#ifdef HAVE_LONG_LONG
+ char *ll_fmt[] = {
+ "%llu",
+ NULL
+ };
+ LLONG ll_nums[] = { 134, 91340, 341, 0203, 1234567890,
128006186140000000LL, 0};
+#endif
int x, y;
int fail = 0;
int num = 0;
+ int l1, l2;
+ char *ss_fmt[] = {
+ "%zd",
+ "%zu",
+ NULL
+ };
+ size_t ss_nums[] = {134, 91340, 123456789, 0203, 1234567890, 0};
printf ("Testing snprintf format codes against system sprintf...\n");
for (x = 0; fp_fmt[x] ; x++) {
for (y = 0; fp_nums[y] != 0 ; y++) {
- int l1 = snprintf(NULL, 0, fp_fmt[x], fp_nums[y]);
- int l2 = snprintf(buf1, sizeof(buf1), fp_fmt[x],
fp_nums[y]);
- sprintf (buf2, fp_fmt[x], fp_nums[y]);
- if (strcmp (buf1, buf2)) {
- printf("snprintf doesn't match Format:
%s\n\tsnprintf = [%s]\n\t sprintf = [%s]\n",
- fp_fmt[x], buf1, buf2);
- fail++;
- }
- if (l1 != l2) {
- printf("snprintf l1 != l2 (%d %d) %s\n", l1,
l2, fp_fmt[x]);
+ buf1[0] = buf2[0] = '\0';
+ l1 = snprintf(buf1, sizeof(buf1), fp_fmt[x],
fp_nums[y]);
+ l2 = sprintf (buf2, fp_fmt[x], fp_nums[y]);
+ buf1[1023] = buf2[1023] = '\0';
+ if (strcmp (buf1, buf2) || (l1 != l2)) {
+ printf("snprintf doesn't match Format:
%s\n\tsnprintf(%d) = [%s]\n\t sprintf(%d) = [%s]\n",
+ fp_fmt[x], l1, buf1, l2, buf2);
fail++;
}
num++;
@@ -929,16 +1395,13 @@ int main (void)
for (x = 0; int_fmt[x] ; x++) {
for (y = 0; int_nums[y] != 0 ; y++) {
- int l1 = snprintf(NULL, 0, int_fmt[x], int_nums[y]);
- int l2 = snprintf(buf1, sizeof(buf1), int_fmt[x],
int_nums[y]);
- sprintf (buf2, int_fmt[x], int_nums[y]);
- if (strcmp (buf1, buf2)) {
- printf("snprintf doesn't match Format:
%s\n\tsnprintf = [%s]\n\t sprintf = [%s]\n",
- int_fmt[x], buf1, buf2);
- fail++;
- }
- if (l1 != l2) {
- printf("snprintf l1 != l2 (%d %d) %s\n", l1,
l2, int_fmt[x]);
+ buf1[0] = buf2[0] = '\0';
+ l1 = snprintf(buf1, sizeof(buf1), int_fmt[x],
int_nums[y]);
+ l2 = sprintf (buf2, int_fmt[x], int_nums[y]);
+ buf1[1023] = buf2[1023] = '\0';
+ if (strcmp (buf1, buf2) || (l1 != l2)) {
+ printf("snprintf doesn't match Format:
%s\n\tsnprintf(%d) = [%s]\n\t sprintf(%d) = [%s]\n",
+ int_fmt[x], l1, buf1, l2, buf2);
fail++;
}
num++;
@@ -947,30 +1410,117 @@ int main (void)
for (x = 0; str_fmt[x] ; x++) {
for (y = 0; str_vals[y] != 0 ; y++) {
- int l1 = snprintf(NULL, 0, str_fmt[x], str_vals[y]);
- int l2 = snprintf(buf1, sizeof(buf1), str_fmt[x],
str_vals[y]);
- sprintf (buf2, str_fmt[x], str_vals[y]);
- if (strcmp (buf1, buf2)) {
- printf("snprintf doesn't match Format:
%s\n\tsnprintf = [%s]\n\t sprintf = [%s]\n",
- str_fmt[x], buf1, buf2);
+ buf1[0] = buf2[0] = '\0';
+ l1 = snprintf(buf1, sizeof(buf1), str_fmt[x],
str_vals[y]);
+ l2 = sprintf (buf2, str_fmt[x], str_vals[y]);
+ buf1[1023] = buf2[1023] = '\0';
+ if (strcmp (buf1, buf2) || (l1 != l2)) {
+ printf("snprintf doesn't match Format:
%s\n\tsnprintf(%d) = [%s]\n\t sprintf(%d) = [%s]\n",
+ str_fmt[x], l1, buf1, l2, buf2);
fail++;
}
- if (l1 != l2) {
- printf("snprintf l1 != l2 (%d %d) %s\n", l1,
l2, str_fmt[x]);
+ num++;
+ }
+ }
+
+#ifdef HAVE_LONG_LONG
+ for (x = 0; ll_fmt[x] ; x++) {
+ for (y = 0; ll_nums[y] != 0 ; y++) {
+ buf1[0] = buf2[0] = '\0';
+ l1 = snprintf(buf1, sizeof(buf1), ll_fmt[x],
ll_nums[y]);
+ l2 = sprintf (buf2, ll_fmt[x], ll_nums[y]);
+ buf1[1023] = buf2[1023] = '\0';
+ if (strcmp (buf1, buf2) || (l1 != l2)) {
+ printf("snprintf doesn't match Format:
%s\n\tsnprintf(%d) = [%s]\n\t sprintf(%d) = [%s]\n",
+ ll_fmt[x], l1, buf1, l2, buf2);
fail++;
}
num++;
}
}
+#endif
+#define BUFSZ 2048
+
+ buf1[0] = buf2[0] = '\0';
+ if ((buf3 = malloc(BUFSZ)) == NULL) {
+ fail++;
+ } else {
+ num++;
+ memset(buf3, 'a', BUFSZ);
+ snprintf(buf1, sizeof(buf1), "%.*s", 1, buf3);
+ buf1[1023] = '\0';
+ if (strcmp(buf1, "a") != 0) {
+ printf("length limit buf1 '%s' expected 'a'\n", buf1);
+ fail++;
+ }
+ }
+
+ buf1[0] = buf2[0] = '\0';
+ l1 = snprintf(buf1, sizeof(buf1), "%4$*1$d %2$s %3$*1$.*1$f", 3, "pos
test", 12.3456, 9);
+ l2 = sprintf(buf2, "%4$*1$d %2$s %3$*1$.*1$f", 3, "pos test", 12.3456,
9);
+ buf1[1023] = buf2[1023] = '\0';
+ if (strcmp(buf1, buf2) || (l1 != l2)) {
+ printf("snprintf doesn't match Format: %s\n\tsnprintf(%d) =
[%s]\n\t sprintf(%d) = [%s]\n",
+ "%4$*1$d %2$s %3$*1$.*1$f", l1, buf1, l2, buf2);
+ fail++;
+ }
+
+ buf1[0] = buf2[0] = '\0';
+ l1 = snprintf(buf1, sizeof(buf1), "%4$*4$d %2$s %3$*4$.*4$f", 3, "pos
test", 12.3456, 9);
+ l2 = sprintf(buf2, "%4$*4$d %2$s %3$*4$.*4$f", 3, "pos test", 12.3456,
9);
+ buf1[1023] = buf2[1023] = '\0';
+ if (strcmp(buf1, buf2)) {
+ printf("snprintf doesn't match Format: %s\n\tsnprintf(%d) =
[%s]\n\t sprintf(%d) = [%s]\n",
+ "%4$*1$d %2$s %3$*1$.*1$f", l1, buf1, l2, buf2);
+ fail++;
+ }
+
+ for (x = 0; ss_fmt[x] ; x++) {
+ for (y = 0; ss_nums[y] != 0 ; y++) {
+ buf1[0] = buf2[0] = '\0';
+ l1 = snprintf(buf1, sizeof(buf1), ss_fmt[x],
ss_nums[y]);
+ l2 = sprintf (buf2, ss_fmt[x], ss_nums[y]);
+ buf1[1023] = buf2[1023] = '\0';
+ if (strcmp (buf1, buf2) || (l1 != l2)) {
+ printf("snprintf doesn't match Format:
%s\n\tsnprintf(%d) = [%s]\n\t sprintf(%d) = [%s]\n",
+ ss_fmt[x], l1, buf1, l2, buf2);
+ fail++;
+ }
+ num++;
+ }
+ }
+#if 0
+ buf1[0] = buf2[0] = '\0';
+ l1 = snprintf(buf1, sizeof(buf1), "%lld", (LLONG)1234567890);
+ l2 = sprintf(buf2, "%lld", (LLONG)1234567890);
+ buf1[1023] = buf2[1023] = '\0';
+ if (strcmp(buf1, buf2)) {
+ printf("snprintf doesn't match Format: %s\n\tsnprintf(%d) =
[%s]\n\t sprintf(%d) = [%s]\n",
+ "%lld", l1, buf1, l2, buf2);
+ fail++;
+ }
+
+ buf1[0] = buf2[0] = '\0';
+ l1 = snprintf(buf1, sizeof(buf1), "%Lf", (LDOUBLE)890.1234567890123);
+ l2 = sprintf(buf2, "%Lf", (LDOUBLE)890.1234567890123);
+ buf1[1023] = buf2[1023] = '\0';
+ if (strcmp(buf1, buf2)) {
+ printf("snprintf doesn't match Format: %s\n\tsnprintf(%d) =
[%s]\n\t sprintf(%d) = [%s]\n",
+ "%Lf", l1, buf1, l2, buf2);
+ fail++;
+ }
+#endif
printf ("%d tests failed out of %d.\n", fail, num);
printf("seeing how many digits we support\n");
{
double v0 = 0.12345678901234567890123456789012345678901;
for (x=0; x<100; x++) {
- snprintf(buf1, sizeof(buf1), "%1.1f", v0*pow(10, x));
- sprintf(buf2, "%1.1f", v0*pow(10, x));
+ double p = pow(10, x);
+ double r = v0*p;
+ snprintf(buf1, sizeof(buf1), "%1.1f", r);
+ sprintf(buf2, "%1.1f", r);
if (strcmp(buf1, buf2)) {
printf("we seem to support %d digits\n", x-1);
break;
@@ -980,4 +1530,4 @@ int main (void)
return 0;
}
-#endif /* SNPRINTF_TEST */
+#endif /* TEST_SNPRINTF */
--
2.20.0.rc2
[PATCH v2 4/8] Test for number of mkdir() arguments, Ladislav Michl, 2018/12/04
[PATCH 8/8] Remove cfg_foreach, Ladislav Michl, 2018/12/04
[PATCH v2 6/8] Refactor devices build, Ladislav Michl, 2018/12/04
[PATCH v2 7/8] Use posix_spawn to run external scripts, Ladislav Michl, 2018/12/04
[PATCH 5/8] Fix compat.c compilation with mingw32, Ladislav Michl, 2018/12/04