aboutsummaryrefslogtreecommitdiff
path: root/lib/snprintf.c
diff options
context:
space:
mode:
Diffstat (limited to 'lib/snprintf.c')
-rw-r--r--lib/snprintf.c133
1 files changed, 88 insertions, 45 deletions
diff --git a/lib/snprintf.c b/lib/snprintf.c
index 3de2a96f..633517de 100644
--- a/lib/snprintf.c
+++ b/lib/snprintf.c
@@ -1,4 +1,8 @@
/*
+ * 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 (papowell@astart.com)
* It may be used for any purpose as long as this notice remains intact
@@ -53,17 +57,57 @@
* 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 <ollie.oldham@metro-optix.com> for spotting it.
+ * few mods to make it easier to compile the tests.
+ * addedd the "Ollie" test to the floating point ones.
+ *
+ * Martin Pool (mbp@samba.org) 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 (mbp@samba.org) 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.
**************************************************************/
-#ifndef NO_CONFIG_H /* for some tests */
+#ifndef NO_CONFIG_H
#include "config.h"
#else
#define NULL 0
-#endif
+#endif
#ifdef TEST_SNPRINTF /* need math library headers for testing */
-#include <math.h>
-#endif
+
+/* 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 */
#ifdef HAVE_STRING_H
#include <string.h>
@@ -75,12 +119,8 @@
#ifdef HAVE_CTYPE_H
#include <ctype.h>
#endif
-#ifdef HAVE_SYS_TYPES_H
#include <sys/types.h>
-#endif
-#ifdef HAVE_STDARG_H
#include <stdarg.h>
-#endif
#ifdef HAVE_STDLIB_H
#include <stdlib.h>
#endif
@@ -89,8 +129,9 @@
/* 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);
void dummy_snprintf(void) {}
-#else
+#endif /* HAVE_SNPRINTF, etc */
#ifdef HAVE_LONG_DOUBLE
#define LDOUBLE long double
@@ -104,29 +145,17 @@
#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)
-#endif
-
#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_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,
- 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
*/
@@ -161,6 +190,19 @@ static void dopr_outch(char *buffer, size_t *currlen, size_t maxlen, char c);
#define MAX(p,q) (((p) >= (q)) ? (p) : (q))
#endif
+/* yes this really must be a ||. Don't muck with this (tridge) */
+#if !defined(HAVE_VSNPRINTF) || !defined(HAVE_C99_VSNPRINTF)
+
+static size_t 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,
+ 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);
+
static size_t dopr(char *buffer, size_t maxlen, const char *format, va_list args_in)
{
char ch;
@@ -345,6 +387,7 @@ static size_t dopr(char *buffer, size_t maxlen, const char *format, va_list args
fvalue = va_arg (args, LDOUBLE);
else
fvalue = va_arg (args, double);
+ fmtfp (buffer, &currlen, maxlen, fvalue, min, max, flags);
break;
case 'G':
flags |= DP_F_UP;
@@ -353,6 +396,7 @@ static size_t dopr(char *buffer, size_t maxlen, const char *format, va_list args
fvalue = va_arg (args, LDOUBLE);
else
fvalue = va_arg (args, double);
+ fmtfp (buffer, &currlen, maxlen, fvalue, min, max, flags);
break;
case 'c':
dopr_outch (buffer, &currlen, maxlen, va_arg (args, int));
@@ -625,7 +669,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;
@@ -684,11 +728,11 @@ static void fmtfp (char *buffer, size_t *currlen, size_t maxlen,
do {
temp = intpart*0.1;
my_modf(temp, &intpart);
- 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); */
+ 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;
@@ -699,11 +743,11 @@ static void fmtfp (char *buffer, size_t *currlen, size_t maxlen,
do {
temp = fracpart*0.1;
my_modf(temp, &fracpart);
- index = (int) ((temp -fracpart +0.05)* 10.0);
- /* index = (int) ((((temp/10) -fracpart) +0.05) *10); */
- /* printf ("%lf, %lf, %ld\n", temp, fracpart, index); */
+ 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--;
}
@@ -773,24 +817,21 @@ 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)
+ int smb_vsnprintf (char *str, size_t count, const char *fmt, va_list args)
{
return dopr(str, count, fmt, args);
}
+#define vsnprintf smb_vsnprintf
#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 smb_snprintf(char *str,size_t count,const char *fmt,...)
{
size_t ret;
va_list ap;
@@ -800,6 +841,7 @@ static void dopr_outch(char *buffer, size_t *currlen, size_t maxlen, char c)
va_end(ap);
return ret;
}
+#define snprintf smb_snprintf
#endif
#endif
@@ -868,8 +910,9 @@ static void dopr_outch(char *buffer, size_t *currlen, size_t maxlen, char c)
"-16.16f",
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, 5.030201, 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",
@@ -977,4 +1020,4 @@ static void dopr_outch(char *buffer, size_t *currlen, size_t maxlen, char c)
return 0;
}
-#endif /* SNPRINTF_TEST */
+#endif /* TEST_SNPRINTF */