[PATCH v3] Update snprintf.c

Previous Topic Next Topic
 
classic Classic list List threaded Threaded
1 message Options
Reply | Threaded
Open this post in threaded view
|

[PATCH v3] Update snprintf.c

Ladislav Michl
From: Fabrizio Gennari <[hidden email]>

Update to the latest (7a5b65c88d3b) version from Samba's repository.
---
 CHANGES:
 -v2: none
 -v3: update to the latest version with fixed whitespaces

 ChangeLog         |    3 +
 common/snprintf.c | 1170 +++++++++++++++++++++++++++++++++------------
 2 files changed, 863 insertions(+), 310 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..7cbef94f 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 ([hidden email])
@@ -30,7 +34,7 @@
  *    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
@@ -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 <[hidden email]> for spotting it.
+ * few mods to make it easier to compile the tests.
+ * addedd the "Ollie" test to the floating point ones.
+ *
+ * Martin Pool ([hidden email]) 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 ([hidden email]) 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 ([hidden email]) 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 ([hidden email]) 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 TEST_SNPRINTF /* need math library headers for testing */
 
-#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
-
-#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
@@ -137,75 +166,154 @@ static void dopr_outch(char *buffer, size_t *currlen, size_t maxlen, char c);
 #define DP_S_DONE    7
 
 /* format flags - Bits */
-#define DP_F_MINUS (1 << 0)
-#define DP_F_PLUS   (1 << 1)
-#define DP_F_SPACE (1 << 2)
-#define DP_F_NUM   (1 << 3)
-#define DP_F_ZERO   (1 << 4)
-#define DP_F_UP     (1 << 5)
-#define DP_F_UNSIGNED (1 << 6)
+#define DP_F_MINUS (1 << 0)
+#define DP_F_PLUS (1 << 1)
+#define DP_F_SPACE (1 << 2)
+#define DP_F_NUM (1 << 3)
+#define DP_F_ZERO (1 << 4)
+#define DP_F_UP (1 << 5)
+#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;
- LLONG value;
- LDOUBLE fvalue;
- char *strvalue;
+struct pr_chunk {
+ int type; /* chunk type */
+ int num; /* parameter number */
  int min;
  int max;
- int state;
  int flags;
  int cflags;
+ int start;
+ int len;
+ LLONG value;
+ LDOUBLE fvalue;
+ char *strvalue;
+ 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 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')
  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;
@@ -235,12 +381,45 @@ static size_t dopr(char *buffer, size_t maxlen, const char *format, va_list args
  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)
  buffer[currlen] = '\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,47 +775,45 @@ 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)
  padlen = 0;
  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 */
  int caps = 0;
-
+
  if (max < 0)
  max = 0;
-
+
  uvalue = value;
-
+
  if(!(flags & DP_F_UNSIGNED)) {
  if( value < 0 ) {
  signvalue = '-';
@@ -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;
@@ -542,14 +888,14 @@ static LDOUBLE abs_val(LDOUBLE value)
 
  if (value < 0)
  result = -value;
-
+
  return result;
 }
 
 static LDOUBLE POW10(int exp)
 {
  LDOUBLE result = 1;
-
+
  while (exp) {
  result *= 10;
  exp--;
@@ -565,7 +911,7 @@ static LLONG ROUND(LDOUBLE value)
  intpart = (LLONG)value;
  value = value - intpart;
  if (value >= 0.5) intpart++;
-
+
  return intpart;
 }
 
@@ -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;
 
@@ -617,7 +963,7 @@ static void fmtfp (char *buffer, size_t *currlen, size_t maxlen,
  int padlen = 0; /* amount to pad */
  int zpadlen = 0;
  int caps = 0;
- int index;
+ int idx;
  double intpart;
  double fracpart;
  double temp;
@@ -651,11 +997,11 @@ static void fmtfp (char *buffer, size_t *currlen, size_t maxlen,
 #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
@@ -665,7 +1011,7 @@ static void fmtfp (char *buffer, size_t *currlen, size_t maxlen,
  my_modf(temp, &intpart);
 
  fracpart = ROUND((POW10(max)) * (ufvalue - intpart));
-
+
  if (fracpart >= POW10(max)) {
  intpart++;
  fracpart -= POW10(max);
@@ -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,14 +1035,13 @@ 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--;
  }
@@ -711,7 +1055,7 @@ static void fmtfp (char *buffer, size_t *currlen, size_t maxlen,
  padlen = 0;
  if (flags & DP_F_MINUS)
  padlen = -padlen; /* Left Justifty */
-
+
  if ((flags & DP_F_ZERO) && (padlen > 0)) {
  if (signvalue) {
  dopr_outch (buffer, currlen, maxlen, signvalue);
@@ -729,7 +1073,7 @@ static void fmtfp (char *buffer, size_t *currlen, size_t maxlen,
  }
  if (signvalue)
  dopr_outch (buffer, currlen, maxlen, signvalue);
-
+
  while (iplace > 0)
  dopr_outch (buffer, currlen, maxlen, iconvert[--iplace]);
 
@@ -743,15 +1087,15 @@ static void fmtfp (char *buffer, size_t *currlen, size_t maxlen,
  */
  if (max > 0) {
  dopr_outch (buffer, currlen, maxlen, '.');
-
+
+ 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,24 +1111,99 @@ 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;
@@ -792,38 +1211,82 @@ int snprintf(char *str,size_t count,const char *fmt,...)
  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
 
 #endif
 
-#ifndef HAVE_VASPRINTF
-int vasprintf(char **ptr, const char *format, va_list ap)
+#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;
-
+
  *ptr = NULL;
  va_start(ap, format);
  ret = vasprintf(ptr, format, ap);
@@ -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++;
+ }
+ 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++;
  }
- if (l1 != l2) {
- printf("snprintf l1 != l2 (%d %d) %s\n", l1, l2, str_fmt[x]);
+ 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.1


_______________________________________________
gnokii-users mailing list
[hidden email]
https://lists.nongnu.org/mailman/listinfo/gnokii-users