summaryrefslogtreecommitdiffstats
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 @@
1/* 1/*
2 * NOTE: If you change this file, please merge it into rsync, samba, etc.
3 */
4
5/*
2 * Copyright Patrick Powell 1995 6 * Copyright Patrick Powell 1995
3 * This code is based on code written by Patrick Powell (papowell@astart.com) 7 * This code is based on code written by Patrick Powell (papowell@astart.com)
4 * It may be used for any purpose as long as this notice remains intact 8 * It may be used for any purpose as long as this notice remains intact
@@ -53,17 +57,57 @@
53 * got rid of fcvt code (twas buggy and made testing harder) 57 * got rid of fcvt code (twas buggy and made testing harder)
54 * added C99 semantics 58 * added C99 semantics
55 * 59 *
60 * date: 2002/12/19 19:56:31; author: herb; state: Exp; lines: +2 -0
61 * actually print args for %g and %e
62 *
63 * date: 2002/06/03 13:37:52; author: jmcd; state: Exp; lines: +8 -0
64 * Since includes.h isn't included here, VA_COPY has to be defined here. I don't
65 * see any include file that is guaranteed to be here, so I'm defining it
66 * locally. Fixes AIX and Solaris builds.
67 *
68 * date: 2002/06/03 03:07:24; author: tridge; state: Exp; lines: +5 -13
69 * put the ifdef for HAVE_VA_COPY in one place rather than in lots of
70 * functions
71 *
72 * date: 2002/05/17 14:51:22; author: jmcd; state: Exp; lines: +21 -4
73 * Fix usage of va_list passed as an arg. Use __va_copy before using it
74 * when it exists.
75 *
76 * date: 2002/04/16 22:38:04; author: idra; state: Exp; lines: +20 -14
77 * Fix incorrect zpadlen handling in fmtfp.
78 * Thanks to Ollie Oldham <ollie.oldham@metro-optix.com> for spotting it.
79 * few mods to make it easier to compile the tests.
80 * addedd the "Ollie" test to the floating point ones.
81 *
82 * Martin Pool (mbp@samba.org) April 2003
83 * Remove NO_CONFIG_H so that the test case can be built within a source
84 * tree with less trouble.
85 * Remove unnecessary SAFE_FREE() definition.
86 *
87 * Martin Pool (mbp@samba.org) May 2003
88 * Put in a prototype for dummy_snprintf() to quiet compiler warnings.
89 *
90 * Move #endif to make sure VA_COPY, LDOUBLE, etc are defined even
91 * if the C library has some snprintf functions already.
56 **************************************************************/ 92 **************************************************************/
57 93
58#ifndef NO_CONFIG_H /* for some tests */ 94#ifndef NO_CONFIG_H
59#include "config.h" 95#include "config.h"
60#else 96#else
61#define NULL 0 97#define NULL 0
62#endif 98#endif
63 99
64#ifdef TEST_SNPRINTF /* need math library headers for testing */ 100#ifdef TEST_SNPRINTF /* need math library headers for testing */
65#include <math.h> 101
66#endif 102/* In test mode, we pretend that this system doesn't have any snprintf
103 * functions, regardless of what config.h says. */
104# undef HAVE_SNPRINTF
105# undef HAVE_VSNPRINTF
106# undef HAVE_C99_VSNPRINTF
107# undef HAVE_ASPRINTF
108# undef HAVE_VASPRINTF
109# include <math.h>
110#endif /* TEST_SNPRINTF */
67 111
68#ifdef HAVE_STRING_H 112#ifdef HAVE_STRING_H
69#include <string.h> 113#include <string.h>
@@ -75,12 +119,8 @@
75#ifdef HAVE_CTYPE_H 119#ifdef HAVE_CTYPE_H
76#include <ctype.h> 120#include <ctype.h>
77#endif 121#endif
78#ifdef HAVE_SYS_TYPES_H
79#include <sys/types.h> 122#include <sys/types.h>
80#endif
81#ifdef HAVE_STDARG_H
82#include <stdarg.h> 123#include <stdarg.h>
83#endif
84#ifdef HAVE_STDLIB_H 124#ifdef HAVE_STDLIB_H
85#include <stdlib.h> 125#include <stdlib.h>
86#endif 126#endif
@@ -89,8 +129,9 @@
89/* only include stdio.h if we are not re-defining snprintf or vsnprintf */ 129/* only include stdio.h if we are not re-defining snprintf or vsnprintf */
90#include <stdio.h> 130#include <stdio.h>
91 /* make the compiler happy with an empty file */ 131 /* make the compiler happy with an empty file */
132 void dummy_snprintf(void);
92 void dummy_snprintf(void) {} 133 void dummy_snprintf(void) {}
93#else 134#endif /* HAVE_SNPRINTF, etc */
94 135
95#ifdef HAVE_LONG_DOUBLE 136#ifdef HAVE_LONG_DOUBLE
96#define LDOUBLE long double 137#define LDOUBLE long double
@@ -104,29 +145,17 @@
104#define LLONG long 145#define LLONG long
105#endif 146#endif
106 147
107/* free memory if the pointer is valid and zero the pointer */
108#ifndef SAFE_FREE
109#define SAFE_FREE(x) do { if ((x) != NULL) {free((x)); (x)=NULL;} } while(0)
110#endif
111
112#ifndef VA_COPY 148#ifndef VA_COPY
113#ifdef HAVE_VA_COPY 149#ifdef HAVE_VA_COPY
150#define VA_COPY(dest, src) va_copy(dest, src)
151#else
152#ifdef HAVE___VA_COPY
114#define VA_COPY(dest, src) __va_copy(dest, src) 153#define VA_COPY(dest, src) __va_copy(dest, src)
115#else 154#else
116#define VA_COPY(dest, src) (dest) = (src) 155#define VA_COPY(dest, src) (dest) = (src)
117#endif 156#endif
118#endif 157#endif
119 158
120static size_t dopr(char *buffer, size_t maxlen, const char *format,
121 va_list args_in);
122static void fmtstr(char *buffer, size_t *currlen, size_t maxlen,
123 char *value, int flags, int min, int max);
124static void fmtint(char *buffer, size_t *currlen, size_t maxlen,
125 long value, int base, int min, int max, int flags);
126static void fmtfp(char *buffer, size_t *currlen, size_t maxlen,
127 LDOUBLE fvalue, int min, int max, int flags);
128static void dopr_outch(char *buffer, size_t *currlen, size_t maxlen, char c);
129
130/* 159/*
131 * dopr(): poor man's version of doprintf 160 * dopr(): poor man's version of doprintf
132 */ 161 */
@@ -161,6 +190,19 @@ static void dopr_outch(char *buffer, size_t *currlen, size_t maxlen, char c);
161#define MAX(p,q) (((p) >= (q)) ? (p) : (q)) 190#define MAX(p,q) (((p) >= (q)) ? (p) : (q))
162#endif 191#endif
163 192
193/* yes this really must be a ||. Don't muck with this (tridge) */
194#if !defined(HAVE_VSNPRINTF) || !defined(HAVE_C99_VSNPRINTF)
195
196static size_t dopr(char *buffer, size_t maxlen, const char *format,
197 va_list args_in);
198static void fmtstr(char *buffer, size_t *currlen, size_t maxlen,
199 char *value, int flags, int min, int max);
200static void fmtint(char *buffer, size_t *currlen, size_t maxlen,
201 long value, int base, int min, int max, int flags);
202static void fmtfp(char *buffer, size_t *currlen, size_t maxlen,
203 LDOUBLE fvalue, int min, int max, int flags);
204static void dopr_outch(char *buffer, size_t *currlen, size_t maxlen, char c);
205
164static size_t dopr(char *buffer, size_t maxlen, const char *format, va_list args_in) 206static size_t dopr(char *buffer, size_t maxlen, const char *format, va_list args_in)
165{ 207{
166 char ch; 208 char ch;
@@ -345,6 +387,7 @@ static size_t dopr(char *buffer, size_t maxlen, const char *format, va_list args
345 fvalue = va_arg (args, LDOUBLE); 387 fvalue = va_arg (args, LDOUBLE);
346 else 388 else
347 fvalue = va_arg (args, double); 389 fvalue = va_arg (args, double);
390 fmtfp (buffer, &currlen, maxlen, fvalue, min, max, flags);
348 break; 391 break;
349 case 'G': 392 case 'G':
350 flags |= DP_F_UP; 393 flags |= DP_F_UP;
@@ -353,6 +396,7 @@ static size_t dopr(char *buffer, size_t maxlen, const char *format, va_list args
353 fvalue = va_arg (args, LDOUBLE); 396 fvalue = va_arg (args, LDOUBLE);
354 else 397 else
355 fvalue = va_arg (args, double); 398 fvalue = va_arg (args, double);
399 fmtfp (buffer, &currlen, maxlen, fvalue, min, max, flags);
356 break; 400 break;
357 case 'c': 401 case 'c':
358 dopr_outch (buffer, &currlen, maxlen, va_arg (args, int)); 402 dopr_outch (buffer, &currlen, maxlen, va_arg (args, int));
@@ -625,7 +669,7 @@ static void fmtfp (char *buffer, size_t *currlen, size_t maxlen,
625 int padlen = 0; /* amount to pad */ 669 int padlen = 0; /* amount to pad */
626 int zpadlen = 0; 670 int zpadlen = 0;
627 int caps = 0; 671 int caps = 0;
628 int index; 672 int idx;
629 double intpart; 673 double intpart;
630 double fracpart; 674 double fracpart;
631 double temp; 675 double temp;
@@ -684,11 +728,11 @@ static void fmtfp (char *buffer, size_t *currlen, size_t maxlen,
684 do { 728 do {
685 temp = intpart*0.1; 729 temp = intpart*0.1;
686 my_modf(temp, &intpart); 730 my_modf(temp, &intpart);
687 index = (int) ((temp -intpart +0.05)* 10.0); 731 idx = (int) ((temp -intpart +0.05)* 10.0);
688 /* index = (int) (((double)(temp*0.1) -intpart +0.05) *10.0); */ 732 /* idx = (int) (((double)(temp*0.1) -intpart +0.05) *10.0); */
689 /* printf ("%llf, %f, %x\n", temp, intpart, index); */ 733 /* printf ("%llf, %f, %x\n", temp, intpart, idx); */
690 iconvert[iplace++] = 734 iconvert[iplace++] =
691 (caps? "0123456789ABCDEF":"0123456789abcdef")[index]; 735 (caps? "0123456789ABCDEF":"0123456789abcdef")[idx];
692 } while (intpart && (iplace < 311)); 736 } while (intpart && (iplace < 311));
693 if (iplace == 311) iplace--; 737 if (iplace == 311) iplace--;
694 iconvert[iplace] = 0; 738 iconvert[iplace] = 0;
@@ -699,11 +743,11 @@ static void fmtfp (char *buffer, size_t *currlen, size_t maxlen,
699 do { 743 do {
700 temp = fracpart*0.1; 744 temp = fracpart*0.1;
701 my_modf(temp, &fracpart); 745 my_modf(temp, &fracpart);
702 index = (int) ((temp -fracpart +0.05)* 10.0); 746 idx = (int) ((temp -fracpart +0.05)* 10.0);
703 /* index = (int) ((((temp/10) -fracpart) +0.05) *10); */ 747 /* idx = (int) ((((temp/10) -fracpart) +0.05) *10); */
704 /* printf ("%lf, %lf, %ld\n", temp, fracpart, index); */ 748 /* printf ("%lf, %lf, %ld\n", temp, fracpart, idx ); */
705 fconvert[fplace++] = 749 fconvert[fplace++] =
706 (caps? "0123456789ABCDEF":"0123456789abcdef")[index]; 750 (caps? "0123456789ABCDEF":"0123456789abcdef")[idx];
707 } while(fracpart && (fplace < 311)); 751 } while(fracpart && (fplace < 311));
708 if (fplace == 311) fplace--; 752 if (fplace == 311) fplace--;
709 } 753 }
@@ -773,24 +817,21 @@ static void dopr_outch(char *buffer, size_t *currlen, size_t maxlen, char c)
773 (*currlen)++; 817 (*currlen)++;
774} 818}
775 819
776/* yes this really must be a ||. Don't muck with this (tridge) */ 820 int smb_vsnprintf (char *str, size_t count, const char *fmt, va_list args)
777#if !defined(HAVE_VSNPRINTF) || !defined(HAVE_C99_VSNPRINTF)
778 int vsnprintf (char *str, size_t count, const char *fmt, va_list args)
779{ 821{
780 return dopr(str, count, fmt, args); 822 return dopr(str, count, fmt, args);
781} 823}
824#define vsnprintf smb_vsnprintf
782#endif 825#endif
783 826
784/* yes this really must be a ||. Don't muck wiith this (tridge) 827/* yes this really must be a ||. Don't muck with this (tridge)
785 * 828 *
786 * The logic for these two is that we need our own definition if the 829 * The logic for these two is that we need our own definition if the
787 * OS *either* has no definition of *sprintf, or if it does have one 830 * OS *either* has no definition of *sprintf, or if it does have one
788 * that doesn't work properly according to the autoconf test. Perhaps 831 * that doesn't work properly according to the autoconf test.
789 * these should really be smb_snprintf to avoid conflicts with buggy
790 * linkers? -- mbp
791 */ 832 */
792#if !defined(HAVE_SNPRINTF) /* || !defined(HAVE_C99_SNPRINTF) */ 833#if !defined(HAVE_SNPRINTF) || !defined(HAVE_C99_VSNPRINTF)
793 int snprintf(char *str,size_t count,const char *fmt,...) 834int smb_snprintf(char *str,size_t count,const char *fmt,...)
794{ 835{
795 size_t ret; 836 size_t ret;
796 va_list ap; 837 va_list ap;
@@ -800,6 +841,7 @@ static void dopr_outch(char *buffer, size_t *currlen, size_t maxlen, char c)
800 va_end(ap); 841 va_end(ap);
801 return ret; 842 return ret;
802} 843}
844#define snprintf smb_snprintf
803#endif 845#endif
804 846
805#endif 847#endif
@@ -868,8 +910,9 @@ static void dopr_outch(char *buffer, size_t *currlen, size_t maxlen, char c)
868 "-16.16f", 910 "-16.16f",
869 NULL 911 NULL
870 }; 912 };
871 double fp_nums[] = { 6442452944.1234, -1.5, 134.21, 91340.2, 341.1234, 0203.9, 0.96, 0.996, 913 double fp_nums[] = { 6442452944.1234, -1.5, 134.21, 91340.2, 341.1234, 203.9, 0.96, 0.996,
872 0.9996, 1.996, 4.136, 5.030201, 0}; 914 0.9996, 1.996, 4.136, 5.030201, 0.00205,
915 /* END LIST */ 0};
873 char *int_fmt[] = { 916 char *int_fmt[] = {
874 "%-1.5d", 917 "%-1.5d",
875 "%1.5d", 918 "%1.5d",
@@ -977,4 +1020,4 @@ static void dopr_outch(char *buffer, size_t *currlen, size_t maxlen, char c)
977 1020
978 return 0; 1021 return 0;
979} 1022}
980#endif /* SNPRINTF_TEST */ 1023#endif /* TEST_SNPRINTF */