diff options
Diffstat (limited to 'lib/snprintf.c')
-rw-r--r-- | lib/snprintf.c | 133 |
1 files changed, 88 insertions, 45 deletions
diff --git a/lib/snprintf.c b/lib/snprintf.c index 3de2a96..633517d 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 | ||
120 | static size_t dopr(char *buffer, size_t maxlen, const char *format, | ||
121 | va_list args_in); | ||
122 | static void fmtstr(char *buffer, size_t *currlen, size_t maxlen, | ||
123 | char *value, int flags, int min, int max); | ||
124 | static void fmtint(char *buffer, size_t *currlen, size_t maxlen, | ||
125 | long value, int base, int min, int max, int flags); | ||
126 | static void fmtfp(char *buffer, size_t *currlen, size_t maxlen, | ||
127 | LDOUBLE fvalue, int min, int max, int flags); | ||
128 | static 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 | |||
196 | static size_t dopr(char *buffer, size_t maxlen, const char *format, | ||
197 | va_list args_in); | ||
198 | static void fmtstr(char *buffer, size_t *currlen, size_t maxlen, | ||
199 | char *value, int flags, int min, int max); | ||
200 | static void fmtint(char *buffer, size_t *currlen, size_t maxlen, | ||
201 | long value, int base, int min, int max, int flags); | ||
202 | static void fmtfp(char *buffer, size_t *currlen, size_t maxlen, | ||
203 | LDOUBLE fvalue, int min, int max, int flags); | ||
204 | static void dopr_outch(char *buffer, size_t *currlen, size_t maxlen, char c); | ||
205 | |||
164 | static size_t dopr(char *buffer, size_t maxlen, const char *format, va_list args_in) | 206 | static 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,...) | 834 | int 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 */ |